diff --git a/Admin.NET/Admin.NET.Application/Configuration/Database.Development.json b/Admin.NET/Admin.NET.Application/Configuration/Database.Development.json index 7ea0723b..f6c3866d 100644 --- a/Admin.NET/Admin.NET.Application/Configuration/Database.Development.json +++ b/Admin.NET/Admin.NET.Application/Configuration/Database.Development.json @@ -4,16 +4,17 @@ // 详细数据库配置见SqlSugar官网(第一个为默认库),极力推荐 PostgreSQL 数据库 // 数据库连接字符串参考地址:https://www.connectionstrings.com/ "DbConnection": { - "EnableConsoleSql": false, // 启用控制台打印SQL + "EnableConsoleSql": true, // 启用控制台打印SQL "ConnectionConfigs": [ { //"ConfigId": "1300000000001", // 默认库标识-禁止修改 - "DbType": "Sqlite", // MySql、SqlServer、Sqlite、Oracle、PostgreSQL、Dm、Kdbndp、Oscar、MySqlConnector、Access、OpenGauss、QuestDB、HG、ClickHouse、GBase、Odbc、Custom + "DbType": "Sqlite", // MySql、SqlServer、Sqlite、Oracle、PostgreSQL、Dm、Kdbndp、Oscar、MySqlConnector、Access、OpenGauss、MongoDB、QuestDB、HG、ClickHouse、GBase、Odbc、Custom "ConnectionString": "DataSource=./Admin.NET.db", // Sqlite - //"ConnectionString": "PORT=5432;DATABASE=xxx;HOST=localhost;PASSWORD=xxx;USER ID=xxx", // PostgreSQL + //"ConnectionString": "PORT=5432;DATABASE=xxx;HOST=localhost;PASSWORD=xxx;USER ID=xxx", // PostgreSQL(Kdbndp、OpenGauss通用) //"ConnectionString": "Server=localhost;Database=xxx;Uid=xxx;Pwd=xxx;SslMode=None;AllowLoadLocalInfile=true;AllowUserVariables=true;", // MySql, //"ConnectionString": "User Id=xxx; Password=xxx; Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL)))", // Oracle //"ConnectionString": "Server=localhost;Database=xxx;User Id=xxx;Password=xxx;Encrypt=True;TrustServerCertificate=True;", // SqlServer + //"ConnectionString": "host=222.71.212.3;Port=27017;Database=testDB;Username= root;Password=123456;authSource=admin;replicaSet=", // MongoDB //"SlaveConnectionConfigs": [ // 读写分离/主从 // { diff --git a/Admin.NET/Admin.NET.Application/Configuration/Database.json b/Admin.NET/Admin.NET.Application/Configuration/Database.json index 7ea0723b..17c1f791 100644 --- a/Admin.NET/Admin.NET.Application/Configuration/Database.json +++ b/Admin.NET/Admin.NET.Application/Configuration/Database.json @@ -8,12 +8,13 @@ "ConnectionConfigs": [ { //"ConfigId": "1300000000001", // 默认库标识-禁止修改 - "DbType": "Sqlite", // MySql、SqlServer、Sqlite、Oracle、PostgreSQL、Dm、Kdbndp、Oscar、MySqlConnector、Access、OpenGauss、QuestDB、HG、ClickHouse、GBase、Odbc、Custom + "DbType": "Sqlite", // MySql、SqlServer、Sqlite、Oracle、PostgreSQL、Dm、Kdbndp、Oscar、MySqlConnector、Access、OpenGauss、MongoDB、QuestDB、HG、ClickHouse、GBase、Odbc、Custom "ConnectionString": "DataSource=./Admin.NET.db", // Sqlite - //"ConnectionString": "PORT=5432;DATABASE=xxx;HOST=localhost;PASSWORD=xxx;USER ID=xxx", // PostgreSQL + //"ConnectionString": "PORT=5432;DATABASE=xxx;HOST=localhost;PASSWORD=xxx;USER ID=xxx", // PostgreSQL(Kdbndp、OpenGauss通用) //"ConnectionString": "Server=localhost;Database=xxx;Uid=xxx;Pwd=xxx;SslMode=None;AllowLoadLocalInfile=true;AllowUserVariables=true;", // MySql, //"ConnectionString": "User Id=xxx; Password=xxx; Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL)))", // Oracle //"ConnectionString": "Server=localhost;Database=xxx;User Id=xxx;Password=xxx;Encrypt=True;TrustServerCertificate=True;", // SqlServer + //"ConnectionString": "host=222.71.212.3;Port=27017;Database=testDB;Username= root;Password=123456;authSource=admin;replicaSet=", // MongoDB //"SlaveConnectionConfigs": [ // 读写分离/主从 // { @@ -26,18 +27,18 @@ // } //], "DbSettings": { - "EnableInitDb": true, // 启用库初始化(若实体没有变化建议关闭) - "EnableInitView": true, // 启用视图初始化(若实体和视图没有变化建议关闭) + "EnableInitDb": false, // 启用库初始化(若实体没有变化建议关闭) + "EnableInitView": false, // 启用视图初始化(若实体和视图没有变化建议关闭) "EnableDiffLog": false, // 启用库表差异日志 "EnableUnderLine": false, // 启用驼峰转下划线 "EnableConnEncrypt": false // 启用数据库连接串加密(国密SM2加解密) }, "TableSettings": { - "EnableInitTable": true, // 启用表初始化(若实体没有变化建议关闭) + "EnableInitTable": false, // 启用表初始化(若实体没有变化建议关闭) "EnableIncreTable": false // 启用表增量更新(只更新贴了特性[IncreTable]的实体表) }, "SeedSettings": { - "EnableInitSeed": true, // 启用种子初始化(若种子没有变化建议关闭) + "EnableInitSeed": false, // 启用种子初始化(若种子没有变化建议关闭) "EnableIncreSeed": false // 启用种子增量更新(只更新贴了特性[IncreSeed]的种子表) } } diff --git a/Admin.NET/Admin.NET.Application/Service/App/Auth/AppAuthService.cs b/Admin.NET/Admin.NET.Application/Service/App/Auth/AppAuthService.cs index e9d73a5f..e6da4e53 100644 --- a/Admin.NET/Admin.NET.Application/Service/App/Auth/AppAuthService.cs +++ b/Admin.NET/Admin.NET.Application/Service/App/Auth/AppAuthService.cs @@ -212,7 +212,10 @@ public class AppAuthService : IDynamicApiController, ITransient // 职位 var pos = await _sysUserRep.ChangeRepository>().GetByIdAsync(user.PosId); // 角色集合 - var roleIds = await _sysUserRep.ChangeRepository>().AsQueryable().Where(u => u.UserId == user.Id).Select(u => u.RoleId).ToListAsync(); + var roles = await _sysUserRep.ChangeRepository>().AsQueryable() + .LeftJoin((u, a) => u.RoleId == a.Id) + .Where(u => u.UserId == user.Id) + .Select((u, a) => new RoleDto { Id = a.Id, Name = a.Name, Code = a.Code }).ToListAsync(); // 接口集合 var apis = (await _sysRoleService.GetUserApiList())[0]; @@ -233,7 +236,7 @@ public class AppAuthService : IDynamicApiController, ITransient OrgType = org?.Type, PosName = pos?.Name, Apis = apis, - RoleIds = roleIds + Roles = roles }; } diff --git a/Admin.NET/Admin.NET.Application/Service/Test/TestService.cs b/Admin.NET/Admin.NET.Application/Service/Test/TestService.cs index 6321f132..1b546135 100644 --- a/Admin.NET/Admin.NET.Application/Service/Test/TestService.cs +++ b/Admin.NET/Admin.NET.Application/Service/Test/TestService.cs @@ -37,7 +37,7 @@ public class TestService : IDynamicApiController /// Redis事件测试 - Payload 🔖 /// /// - public async void EventTestAsync() + public async Task EventTestAsync() { await _eventPublisher.PublishAsync(CommonConst.SendErrorMail, "Admin.NET"); } diff --git a/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj b/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj index 1d96e69d..c94a985d 100644 --- a/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj +++ b/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj @@ -22,52 +22,53 @@ - + - - - + + + - - - - - + + + + + - - + + - - - + + + + - + - - + + - - + + @@ -84,9 +85,9 @@ - - - + + + diff --git a/Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseService.cs b/Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseService.cs index d44f31ed..281347cb 100644 --- a/Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseService.cs +++ b/Admin.NET/Admin.NET.Core/Ai/Service/SSE/SseService.cs @@ -32,7 +32,7 @@ public class SseService : ControllerBase Response.Headers.Append("Cache-Control", "no-cache"); Response.Headers.Append("Connection", "keep-alive"); Response.Headers.Append("X-Accel-Buffering", "no"); // Nginx - + var channel = _sseChannelManager.Register(id); var deepThinkingChannel = _sseDeepThinkingChannelManager.Register(id); try diff --git a/Admin.NET/Admin.NET.Core/Attribute/MaskNewtonsoftJsonConverter.cs b/Admin.NET/Admin.NET.Core/Attribute/MaskNewtonsoftJsonConverter.cs index 6b44ab59..49f85b04 100644 --- a/Admin.NET/Admin.NET.Core/Attribute/MaskNewtonsoftJsonConverter.cs +++ b/Admin.NET/Admin.NET.Core/Attribute/MaskNewtonsoftJsonConverter.cs @@ -24,6 +24,22 @@ public class MaskNewtonsoftJsonConverter : JsonConverter } } +/// +/// 姓名掩码 +/// +public class MaskNameNewtonsoftJsonConverter : JsonConverter +{ + public override string ReadJson(JsonReader reader, Type objectType, string existingValue, bool hasExistingValue, JsonSerializer serializer) + { + return reader.Value.ToString(); + } + + public override void WriteJson(JsonWriter writer, string value, JsonSerializer serializer) + { + writer.WriteValue(value?.ToString().MaskName()); + } +} + /// /// 身份证掩码 /// diff --git a/Admin.NET/Admin.NET.Core/Attribute/MaskSystemTextJsonConverter.cs b/Admin.NET/Admin.NET.Core/Attribute/MaskSystemTextJsonConverter.cs index 63c6a982..38dfa7e5 100644 --- a/Admin.NET/Admin.NET.Core/Attribute/MaskSystemTextJsonConverter.cs +++ b/Admin.NET/Admin.NET.Core/Attribute/MaskSystemTextJsonConverter.cs @@ -25,6 +25,22 @@ public class MaskSystemTextJsonConverter : JsonConverter } } +/// +/// 姓名掩码 +/// +public class MaskNameSystemTextJsonConverter : JsonConverter +{ + public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return reader.GetString(); + } + + public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) + { + writer.WriteStringValue(value?.ToString().MaskName()); + } +} + /// /// 身份证掩码 /// diff --git a/Admin.NET/Admin.NET.Core/Const/CacheConst.cs b/Admin.NET/Admin.NET.Core/Const/CacheConst.cs index 8a141f90..12f7e5a4 100644 --- a/Admin.NET/Admin.NET.Core/Const/CacheConst.cs +++ b/Admin.NET/Admin.NET.Core/Const/CacheConst.cs @@ -110,4 +110,9 @@ public class CacheConst /// Excel临时文件缓存 /// public const string KeyExcelTemp = "sys_excel_temp:"; + + /// + /// 列配置缓存 + /// + public const string KeyColumnCustom = "sys_column_custom:"; } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Entity/SysColumnCustom.cs b/Admin.NET/Admin.NET.Core/Entity/SysColumnCustom.cs new file mode 100644 index 00000000..4b47a398 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Entity/SysColumnCustom.cs @@ -0,0 +1,54 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// Vxe表格列配置 +/// +[SugarTable(null, "Vxe表格列配置")] +[SysTable] +[SugarIndex("i_{table}_u", nameof(UserId), OrderByType.Asc)] +[SugarIndex("i_{table}_g", nameof(GridId), OrderByType.Asc)] +public class SysColumnCustom : EntityTenantId +{ + /// + /// 用户Id + /// + [SugarColumn(ColumnDescription = "用户Id")] + public long UserId { get; set; } + + /// + /// 表格Id + /// + [SugarColumn(ColumnDescription = "表格Id", Length = 128)] + [MaxLength(128)] + public string GridId { get; set; } + + /// + /// 冻结列状态数据 + /// + [SugarColumn(ColumnDescription = "冻结列状态数据", ColumnDataType = StaticConfig.CodeFirst_BigString)] + public string? FixedData { get; set; } + + /// + /// 列宽状态数据 + /// + [SugarColumn(ColumnDescription = "列宽状态数据", ColumnDataType = StaticConfig.CodeFirst_BigString)] + public string? ResizableData { get; set; } + + /// + /// 列顺序数据 + /// + [SugarColumn(ColumnDescription = "列顺序数据", ColumnDataType = StaticConfig.CodeFirst_BigString)] + public string? SortData { get; set; } + + /// + /// 显示/隐藏列状态数据 + /// + [SugarColumn(ColumnDescription = "显示/隐藏列状态数据", ColumnDataType = StaticConfig.CodeFirst_BigString)] + public string? VisibleData { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Entity/SysConfigTenant.cs b/Admin.NET/Admin.NET.Core/Entity/SysConfigTenant.cs index 86aa5a46..41cfd8d9 100644 --- a/Admin.NET/Admin.NET.Core/Entity/SysConfigTenant.cs +++ b/Admin.NET/Admin.NET.Core/Entity/SysConfigTenant.cs @@ -12,7 +12,7 @@ namespace Admin.NET.Core; [SugarTable(null, "系统租户配置参数表")] [SysTable] [SugarIndex("i_{table}_n", nameof(Name), OrderByType.Asc)] -[SugarIndex("i_{table}_c", nameof(Code), OrderByType.Asc, IsUnique = true)] +[SugarIndex("i_{table}_c", nameof(Code), OrderByType.Asc, nameof(TenantId), OrderByType.Asc, IsUnique = true)] public partial class SysConfigTenant : SysConfig, ITenantIdFilter { /// diff --git a/Admin.NET/Admin.NET.Core/Entity/SysDictDataTenant.cs b/Admin.NET/Admin.NET.Core/Entity/SysDictDataTenant.cs index 2632eb09..85fb50ab 100644 --- a/Admin.NET/Admin.NET.Core/Entity/SysDictDataTenant.cs +++ b/Admin.NET/Admin.NET.Core/Entity/SysDictDataTenant.cs @@ -11,7 +11,7 @@ namespace Admin.NET.Core; /// [SugarTable(null, "系统租户字典值表")] [SysTable] -[SugarIndex("i_{table}_c", nameof(Code), OrderByType.Asc)] +[SugarIndex("i_{table}_c", nameof(Code), OrderByType.Asc, nameof(TenantId), OrderByType.Asc)] public partial class SysDictDataTenant : SysDictData, ITenantIdFilter { /// diff --git a/Admin.NET/Admin.NET.Core/Entity/SysFileContent.cs b/Admin.NET/Admin.NET.Core/Entity/SysFileContent.cs index e0e071a8..896e6ac1 100644 --- a/Admin.NET/Admin.NET.Core/Entity/SysFileContent.cs +++ b/Admin.NET/Admin.NET.Core/Entity/SysFileContent.cs @@ -22,6 +22,6 @@ public partial class SysFileContent : EntityBase /// /// 文件内容 /// - [SugarColumn(ColumnDescription = "文件内容", ColumnDataType = "blob,bytea,binary", IsNullable = false)] + [SugarColumn(ColumnDescription = "文件内容", IsNullable = false)] public byte[] Content { get; set; } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Entity/SysReportConfig.cs b/Admin.NET/Admin.NET.Core/Entity/SysReportConfig.cs new file mode 100644 index 00000000..bd27eff1 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Entity/SysReportConfig.cs @@ -0,0 +1,93 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 系统报表配置表 +/// +[SugarTable(null, "系统报表配置表")] +[SysTable] +public class SysReportConfig : EntityBase +{ + /// + /// 名称 + /// + [SugarColumn(ColumnDescription = "名称", Length = 254)] + [MaxLength(254)] + public string Name { get; set; } + + /// + /// 描述 + /// + [SugarColumn(ColumnDescription = "描述", Length = 512)] + [MaxLength(512)] + public string? Description { get; set; } + + /// + /// 数据源类型 + /// + [SugarColumn(ColumnDescription = "数据源类型")] + public ReportConfigDsTypeEnum DsType { get; set; } + + /// + /// 数据源 + /// + [SugarColumn(ColumnDescription = "数据源", Length = 64)] + [MaxLength(64)] + public string? DataSource { get; set; } + + /// + /// 分组Id + /// + [SugarColumn(ColumnDescription = "分组Id")] + public long? GroupId { get; set; } + + /// + /// 分组 + /// + [Navigate(NavigateType.OneToOne, nameof(GroupId))] + public SysReportGroup Group { get; set; } + + /// + /// 脚本语句 + /// + [SugarColumn(ColumnDescription = "脚本语句", ColumnDataType = StaticConfig.CodeFirst_BigString)] + public string? SqlScript { get; set; } + + /// + /// 接口地址 + /// + [SugarColumn(ColumnDescription = "接口地址", Length = 1024)] + [MaxLength(1024)] + public string? ApiUrl { get; set; } + + /// + /// 接口请求方式 + /// + [SugarColumn(ColumnDescription = "接口请求方式", Length = 16)] + [MaxLength(16)] + public string? ApiHttpMethod { get; set; } + + /// + /// 接口参数 + /// + [SugarColumn(ColumnDescription = "接口参数", Length = 1024)] + [MaxLength(1024)] + public string? ApiParams { get; set; } + + /// + /// 参数 + /// + [SugarColumn(ColumnDescription = "参数", ColumnDataType = StaticConfig.CodeFirst_BigString)] + public string? Params { get; set; } + + /// + /// 列表字段 + /// + [SugarColumn(ColumnDescription = "列表字段", ColumnDataType = StaticConfig.CodeFirst_BigString)] + public string? Fields { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Entity/SysReportDataSource.cs b/Admin.NET/Admin.NET.Core/Entity/SysReportDataSource.cs new file mode 100644 index 00000000..34f4eeea --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Entity/SysReportDataSource.cs @@ -0,0 +1,43 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 系统报表数据源 +/// +[SugarTable(null, "系统报表数据源表")] +[SysTable] +public class SysReportDataSource : EntityBase +{ + /// + /// 名称 + /// + [SugarColumn(ColumnDescription = "名称", Length = 254)] + [MaxLength(254)] + public string Name { get; set; } + + /// + /// 数据库类型 + /// + [SugarColumn(ColumnDescription = "数据库类型", Length = 32)] + [MaxLength(32)] + public string DbType { get; set; } + + /// + /// 连接字符串 + /// + [SugarColumn(ColumnDescription = "连接字符串", Length = 512)] + [MaxLength(512)] + public string ConnectionString { get; set; } + + /// + /// 备注 + /// + [SugarColumn(ColumnDescription = "备注", Length = 128)] + [MaxLength(128)] + public string? Remark { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Entity/SysReportGroup.cs b/Admin.NET/Admin.NET.Core/Entity/SysReportGroup.cs new file mode 100644 index 00000000..6308d2d2 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Entity/SysReportGroup.cs @@ -0,0 +1,29 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 系统报表分组 +/// +[SugarTable(null, "系统报表分组表")] +[SysTable] +public class SysReportGroup : EntityBase +{ + /// + /// 编码 + /// + [SugarColumn(ColumnDescription = "编码", Length = 64)] + [MaxLength(64)] + public string Number { get; set; } + + /// + /// 名称 + /// + [SugarColumn(ColumnDescription = "名称", Length = 254)] + [MaxLength(254)] + public string Name { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Entity/SysRole.cs b/Admin.NET/Admin.NET.Core/Entity/SysRole.cs index ead5d302..cc88fdec 100644 --- a/Admin.NET/Admin.NET.Core/Entity/SysRole.cs +++ b/Admin.NET/Admin.NET.Core/Entity/SysRole.cs @@ -44,8 +44,8 @@ public partial class SysRole : EntityTenant /// /// 是否是内置(Y-是,N-否) /// - [SugarColumn(ColumnDescription = "是否是内置", DefaultValue = "1")] - public YesNoEnum SysFlag { get; set; } = YesNoEnum.Y; + [SugarColumn(ColumnDescription = "是否是内置", DefaultValue = "2")] + public YesNoEnum SysFlag { get; set; } = YesNoEnum.N; /// /// 备注 diff --git a/Admin.NET/Admin.NET.Core/Enum/ErrorCodeEnum.cs b/Admin.NET/Admin.NET.Core/Enum/ErrorCodeEnum.cs index 71ce30c5..96eef0e1 100644 --- a/Admin.NET/Admin.NET.Core/Enum/ErrorCodeEnum.cs +++ b/Admin.NET/Admin.NET.Core/Enum/ErrorCodeEnum.cs @@ -158,9 +158,9 @@ public enum ErrorCodeEnum D1018, /// - /// 禁止删除系统管理员角色 + /// 禁止删除系统内置角色 /// - [ErrorCodeItemMetadata("禁止删除系统管理员角色")] + [ErrorCodeItemMetadata("禁止删除系统内置角色")] D1019, /// @@ -241,6 +241,12 @@ public enum ErrorCodeEnum [ErrorCodeItemMetadata("手机号已存在")] D1032, + /// + /// 无权操作此账号 + /// + [ErrorCodeItemMetadata("无权操作此账号")] + D1033, + /// /// 父机构不存在 /// @@ -314,7 +320,7 @@ public enum ErrorCodeEnum D3000, /// - /// 字典类型已存在 + /// 字典类型已存在,名称或编码重复 /// [ErrorCodeItemMetadata("字典类型已存在,名称或编码重复")] D3001, @@ -846,4 +852,28 @@ public enum ErrorCodeEnum /// [ErrorCodeItemMetadata("身份标识已存在")] O1000, + + /// + /// 名称已存在 + /// + [ErrorCodeItemMetadata("名称已存在")] + C1000, + + /// + /// 数据源类型为 Sql 才允许执行 + /// + [ErrorCodeItemMetadata("数据源类型为 Sql 才允许执行")] + C1001, + + /// + /// 数据源不存在 + /// + [ErrorCodeItemMetadata("数据源不存在")] + C1002, + + /// + /// 编码已存在 + /// + [ErrorCodeItemMetadata("编码已存在")] + C1003, } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Enum/ReportConfigDsTypeEnum.cs b/Admin.NET/Admin.NET.Core/Enum/ReportConfigDsTypeEnum.cs new file mode 100644 index 00000000..4633e9f0 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Enum/ReportConfigDsTypeEnum.cs @@ -0,0 +1,25 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 报表配置数据源类型 +/// +public enum ReportConfigDsTypeEnum +{ + /// + /// Sql + /// + [Description("Sql")] + Sql = 0, + + /// + /// Api + /// + [Description("Api")] + Api = 1, +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs b/Admin.NET/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs index 0ad569c3..511abe13 100644 --- a/Admin.NET/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs +++ b/Admin.NET/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs @@ -57,8 +57,8 @@ public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable FullRedis redis = (FullRedis)cacheProvider.Cache; var clusterOpt = App.GetConfig("Cluster", true); _queueBroadcast = redis.GetStream(routeKey + ":broadcast"); - _queueBroadcast.Group = clusterOpt.ServerId;//根据服务器标识分配到不同的分组里 - _queueBroadcast.Expire = TimeSpan.FromSeconds(10);//消息10秒过期() + _queueBroadcast.Group = clusterOpt.ServerId; //根据服务器标识分配到不同的分组里 + _queueBroadcast.Expire = TimeSpan.FromSeconds(10); //消息10秒过期() _queueBroadcast.ConsumeAsync(OnConsumeBroadcast); // 创建队列消息订阅者,只要有一个服务节点消费了消息即可 @@ -98,6 +98,7 @@ public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable Console.WriteLine($"有消息要处理{ces.EventId},{ces.Payload}"); Console.ForegroundColor = oriColor; } + await _channel.Writer.WriteAsync(ces, cancel); } @@ -151,9 +152,9 @@ public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable /// /// 释放非托管资源 /// - public async void Dispose() + public void Dispose() { - await _eventConsumer.Stop(); + _eventConsumer.Stop().GetAwaiter().GetResult(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Extension/ObjectExtension.cs b/Admin.NET/Admin.NET.Core/Extension/ObjectExtension.cs index 5c8f54d1..df3c7ef0 100644 --- a/Admin.NET/Admin.NET.Core/Extension/ObjectExtension.cs +++ b/Admin.NET/Admin.NET.Core/Extension/ObjectExtension.cs @@ -134,6 +134,19 @@ public static partial class ObjectExtension }; } + /// + /// 姓名掩码 + /// + /// 姓名 + /// 掩码符 + /// + public static string MaskName(this string name, char mask = '*') + { + if (string.IsNullOrEmpty(name) || name.Length < 2) return name; + + return string.Concat(name.AsSpan(0, 1), mask.ToString(), name.AsSpan(2)); + } + /// /// 身份证号掩码 /// diff --git a/Admin.NET/Admin.NET.Core/Extension/RepositoryExtension.cs b/Admin.NET/Admin.NET.Core/Extension/RepositoryExtension.cs index f730e1d8..37a80069 100644 --- a/Admin.NET/Admin.NET.Core/Extension/RepositoryExtension.cs +++ b/Admin.NET/Admin.NET.Core/Extension/RepositoryExtension.cs @@ -145,12 +145,12 @@ public static class RepositoryExtension typeAdapterConfig.ForType().IgnoreNullValues(true); Mapper mapper = new(typeAdapterConfig); // 务必将mapper设为单实例 var nowPagerInput = mapper.Map(pageInput); - // 排序是否可用-排序字段和排序顺序都为非空才启用排序 - if (!string.IsNullOrEmpty(nowPagerInput.Field) && !string.IsNullOrEmpty(nowPagerInput.Order)) + // 排序是否可用-排序字段为非空才启用排序,排序顺序默认为倒序 + if (!string.IsNullOrEmpty(nowPagerInput.Field)) { - var col = queryable.Context.EntityMaintenance.GetEntityInfo().Columns.FirstOrDefault(u => u.PropertyName.Equals(nowPagerInput.Field, StringComparison.CurrentCultureIgnoreCase)); - var dbColumnName = col != null ? col.DbColumnName : nowPagerInput.Field; - orderStr = $"{prefix}{iSqlBuilder.GetTranslationColumnName(dbColumnName)} {(nowPagerInput.Order == nowPagerInput.DescStr ? "Desc" : "Asc")}"; + nowPagerInput.Field = Regex.Replace(nowPagerInput.Field, @"[\s;()\-'@=/%]", ""); //过滤掉一些关键字符防止构造特殊SQL语句注入 + var orderByDbName = queryable.Context.EntityMaintenance.GetDbColumnName(nowPagerInput.Field);//防止注入,类中只要不存在属性名就会报错 + orderStr = $"{prefix}{iSqlBuilder.GetTranslationColumnName(orderByDbName)} {(string.IsNullOrEmpty(nowPagerInput.Order) || nowPagerInput.Order.Equals(nowPagerInput.DescStr, StringComparison.OrdinalIgnoreCase) ? "Desc" : "Asc")}"; } return queryable.OrderByIF(!string.IsNullOrWhiteSpace(orderStr), orderStr); } diff --git a/Admin.NET/Admin.NET.Core/SeedData/SysCodeGenTemplateSeedData.cs b/Admin.NET/Admin.NET.Core/SeedData/SysCodeGenTemplateSeedData.cs index 9b397eb9..f50f6c4f 100644 --- a/Admin.NET/Admin.NET.Core/SeedData/SysCodeGenTemplateSeedData.cs +++ b/Admin.NET/Admin.NET.Core/SeedData/SysCodeGenTemplateSeedData.cs @@ -59,7 +59,7 @@ public class SysCodeGenTemplateSeedData : ISqlSugarEntitySeedData new SysDictData{ Id=1300000000109, DictTypeId=1300000000101, Label="文本域", Value="InputTextArea", OrderNo=100, Remark="文本域", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00") }, new SysDictData{ Id=1300000000110, DictTypeId=1300000000101, Label="上传", Value="Upload", OrderNo=100, Remark="上传", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00") }, new SysDictData{ Id=1300000000111, DictTypeId=1300000000101, Label="开关", Value="Switch", OrderNo=100, Remark="开关", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00") }, + new SysDictData{ Id=1300000000112, DictTypeId=1300000000101, Label="富文本", Value="RichTextEditor", OrderNo=100, Remark="富文本", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00") }, new SysDictData{ Id=1300000000201, DictTypeId=1300000000102, Label="等于", Value="==", OrderNo=1, Remark="等于", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00") }, new SysDictData{ Id=1300000000202, DictTypeId=1300000000102, Label="模糊", Value="like", OrderNo=1, Remark="模糊", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00") }, diff --git a/Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs b/Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs index 31c49312..a96472dd 100644 --- a/Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs +++ b/Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs @@ -59,7 +59,7 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData new SysMenu{ Id=1310000000151, Pid=1310000000101, Title="职位管理", Path="/system/pos", Name="sysPos", Component="/system/pos/index",Icon="ele-Mug", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 }, new SysMenu{ Id=1310000000152, Pid=1310000000151, Title="查询", Permission="sysPos/page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, - new SysMenu{ Id=1310000000153, Pid=1310000000151, Title="列表", Permission="sysPos/list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, + //new SysMenu{ Id=1310000000153, Pid=1310000000151, Title="列表", Permission="sysPos/list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, new SysMenu{ Id=1310000000154, Pid=1310000000151, Title="编辑", Permission="sysPos/update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, new SysMenu{ Id=1310000000155, Pid=1310000000151, Title="增加", Permission="sysPos/add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, new SysMenu{ Id=1310000000156, Pid=1310000000151, Title="删除", Permission="sysPos/delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, @@ -211,11 +211,25 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData new SysMenu{ Id=1310000000641, Pid=1310000000601, Title="系统接口", Path="/develop/api", Name="sysApi", Component="layout/routerView/iframe", IsIframe=true, OutLink="http://localhost:5005", Icon="ele-Help", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=140 }, new SysMenu{ Id=1310000000651, Pid=1310000000601, Title="接口压测", Path="/develop/stressTest", Name="sysStressTest", Component="/system/stressTest/index", Icon="ele-Compass", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2024-12-28 00:00:00"), OrderNo=150 }, - new SysMenu{ Id=1310000000701, Pid=0, Title="帮助文档", Path="/doc", Name="doc", Component="Layout", Icon="ele-Notebook", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=14000 }, - new SysMenu{ Id=1310000000711, Pid=1310000000701, Title="框架教程", Path="/doc/admin", Name="sysAdmin", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://adminnet.top/", Icon="ele-Sunny", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, - new SysMenu{ Id=1310000000721, Pid=1310000000701, Title="SqlSugar", Path="/doc/SqlSugar", Name="sysSqlSugar", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://www.donet5.com/Home/Doc", Icon="ele-Coin", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 }, + new SysMenu{ Id=1310000000701, Pid=0, Title="报表开发", Path="/report", Name="report", Component="Layout", Icon="ele-Histogram", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=14000 }, + new SysMenu{ Id=1310000000711, Pid=1310000000701, Title="数据源配置", Path="/report/reportDataSource", Name="sysReportDataSource", Component="/system/reportDataSource/index", Icon="ele-Filter", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, + new SysMenu{ Id=1310000000712, Pid=1310000000711, Title="查询", Permission="sysReportDataSource/page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, + new SysMenu{ Id=1310000000713, Pid=1310000000711, Title="编辑", Permission="sysReportDataSource/update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, + new SysMenu{ Id=1310000000714, Pid=1310000000711, Title="增加", Permission="sysReportDataSource/add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, + new SysMenu{ Id=1310000000715, Pid=1310000000711, Title="删除", Permission="sysReportDataSource/delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, + new SysMenu{ Id=1310000000716, Pid=1310000000711, Title="复制", Permission="sysReportDataSource/copy", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, + new SysMenu{ Id=1310000000721, Pid=1310000000701, Title="报表配置", Path="/report/reportConfig", Name="sysReportConfig", Component="/system/reportConfig/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 }, + new SysMenu{ Id=1310000000731, Pid=1310000000721, Title="查询", Permission="sysReportConfig/page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, + new SysMenu{ Id=1310000000741, Pid=1310000000721, Title="编辑", Permission="sysReportConfig/update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, + new SysMenu{ Id=1310000000751, Pid=1310000000721, Title="增加", Permission="sysReportConfig/add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, + new SysMenu{ Id=1310000000761, Pid=1310000000721, Title="删除", Permission="sysReportConfig/delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, - new SysMenu{ Id=1310000000801, Pid=0, Title="关于项目", Path="/about", Name="about", Component="/about/index", Icon="ele-InfoFilled", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2023-03-12 00:00:00"), OrderNo=15000 }, - ]; + new SysMenu{ Id=1320000000101, Pid=0, Title="帮助文档", Path="/doc", Name="doc", Component="Layout", Icon="ele-Notebook", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=15000 }, + new SysMenu{ Id=1320000000111, Pid=1320000000101, Title="框架教程", Path="/doc/admin", Name="sysAdmin", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://adminnet.top/", Icon="ele-Sunny", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 }, + new SysMenu{ Id=1320000000121, Pid=1320000000101, Title="SqlSugar", Path="/doc/SqlSugar", Name="sysSqlSugar", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://www.donet5.com/Home/Doc", Icon="ele-Coin", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 }, + + new SysMenu{ Id=1320000000201, Pid=0, Title="关于项目", Path="/about", Name="about", Component="/about/index", Icon="ele-InfoFilled", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2023-03-12 00:00:00"), OrderNo=16000 }, + + ]; } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/SeedData/SysPosSeedData.cs b/Admin.NET/Admin.NET.Core/SeedData/SysPosSeedData.cs index 0218bd28..cd2af492 100644 --- a/Admin.NET/Admin.NET.Core/SeedData/SysPosSeedData.cs +++ b/Admin.NET/Admin.NET.Core/SeedData/SysPosSeedData.cs @@ -21,21 +21,12 @@ public class SysPosSeedData : ISqlSugarEntitySeedData return [ new SysPos{ Id=1300000000101, Name="党委书记", Code="dwsj", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="党委书记", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000102, Name="董事长", Code="dsz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="董事长", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000103, Name="副董事长", Code="fdsz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副董事长", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000104, Name="总经理", Code="zjl", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="总经理", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000105, Name="副总经理", Code="fzjl", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副总经理", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000106, Name="部门经理", Code="bmjl", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="部门经理", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000107, Name="部门副经理", Code="bmfjl", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="部门副经理", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000108, Name="主任", Code="zr", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="主任", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000109, Name="副主任", Code="fzr", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副主任", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000110, Name="局长", Code="jz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="局长", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000111, Name="副局长", Code="fjz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副局长", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000112, Name="科长", Code="kz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="科长", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000113, Name="副科长", Code="fkz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副科长", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000114, Name="财务", Code="cw", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="财务", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000115, Name="职员", Code="zy", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="职员", TenantId=SqlSugarConst.DefaultTenantId }, - new SysPos{ Id=1300000000116, Name="其他", Code="qt", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="其他", TenantId=SqlSugarConst.DefaultTenantId }, + new SysPos{ Id=1300000000102, Name="局长", Code="jz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="局长", TenantId=SqlSugarConst.DefaultTenantId }, + new SysPos{ Id=1300000000103, Name="副局长", Code="fjz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副局长", TenantId=SqlSugarConst.DefaultTenantId }, + new SysPos{ Id=1300000000104, Name="科长", Code="kz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="科长", TenantId=SqlSugarConst.DefaultTenantId }, + new SysPos{ Id=1300000000105, Name="副科长", Code="fkz", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="副科长", TenantId=SqlSugarConst.DefaultTenantId }, + new SysPos{ Id=1300000000106, Name="职员", Code="zy", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="职员", TenantId=SqlSugarConst.DefaultTenantId }, + new SysPos{ Id=1300000000107, Name="其他", Code="qt", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="其他", TenantId=SqlSugarConst.DefaultTenantId }, ]; } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/SeedData/SysRoleMenuSeedData.cs b/Admin.NET/Admin.NET.Core/SeedData/SysRoleMenuSeedData.cs index fd1732c7..6147ee1d 100644 --- a/Admin.NET/Admin.NET.Core/SeedData/SysRoleMenuSeedData.cs +++ b/Admin.NET/Admin.NET.Core/SeedData/SysRoleMenuSeedData.cs @@ -48,16 +48,17 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData new SysRoleMenu{ Id=1300000000147, RoleId=1300000000101, MenuId=1310000000137 }, new SysRoleMenu{ Id=1300000000148, RoleId=1300000000101, MenuId=1310000000138 }, new SysRoleMenu{ Id=1300000000149, RoleId=1300000000101, MenuId=1310000000139 }, + new SysRoleMenu{ Id=1300000000150, RoleId=1300000000101, MenuId=1310000000140 }, // 机构管理 new SysRoleMenu{ Id=1300000000151, RoleId=1300000000101, MenuId=1310000000141 }, - new SysRoleMenu{ Id=1300000000152, RoleId=1300000000101, MenuId=1310000000142 }, + //new SysRoleMenu{ Id=1300000000152, RoleId=1300000000101, MenuId=1310000000142 }, new SysRoleMenu{ Id=1300000000153, RoleId=1300000000101, MenuId=1310000000143 }, new SysRoleMenu{ Id=1300000000154, RoleId=1300000000101, MenuId=1310000000144 }, new SysRoleMenu{ Id=1300000000155, RoleId=1300000000101, MenuId=1310000000145 }, // 职位管理 new SysRoleMenu{ Id=1300000000161, RoleId=1300000000101, MenuId=1310000000151 }, new SysRoleMenu{ Id=1300000000162, RoleId=1300000000101, MenuId=1310000000152 }, - new SysRoleMenu{ Id=1300000000163, RoleId=1300000000101, MenuId=1310000000153 }, + //new SysRoleMenu{ Id=1300000000163, RoleId=1300000000101, MenuId=1310000000153 }, new SysRoleMenu{ Id=1300000000164, RoleId=1300000000101, MenuId=1310000000154 }, new SysRoleMenu{ Id=1300000000165, RoleId=1300000000101, MenuId=1310000000155 }, new SysRoleMenu{ Id=1300000000166, RoleId=1300000000101, MenuId=1310000000156 }, @@ -74,7 +75,6 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData new SysRoleMenu{ Id=1300000000184, RoleId=1300000000101, MenuId=1310000000174 }, new SysRoleMenu{ Id=1300000000185, RoleId=1300000000101, MenuId=1310000000175 }, new SysRoleMenu{ Id=1300000000186, RoleId=1300000000101, MenuId=1310000000176 }, - new SysRoleMenu{ Id=1300000000187, RoleId=1300000000101, MenuId=1310000000177 }, // 三方账号 new SysRoleMenu{ Id=1300000000191, RoleId=1300000000101, MenuId=1310000000181 }, new SysRoleMenu{ Id=1300000000192, RoleId=1300000000101, MenuId=1310000000182 }, @@ -93,8 +93,11 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData ////// 平台管理 new SysRoleMenu{ Id=1300000000201, RoleId=1300000000101, MenuId=1310000000301 }, // 菜单管理 - new SysRoleMenu{ Id=1300000000221, RoleId=1300000000101, MenuId=1310000000322 }, - // 字典管理 + new SysRoleMenu{ Id=1300000000221, RoleId=1300000000101, MenuId=1310000000321 }, + new SysRoleMenu{ Id=1300000000222, RoleId=1300000000101, MenuId=1310000000323 }, + new SysRoleMenu{ Id=1300000000223, RoleId=1300000000101, MenuId=1310000000324 }, + new SysRoleMenu{ Id=1300000000224, RoleId=1300000000101, MenuId=1310000000325 }, + // 配置参数 new SysRoleMenu{ Id=1300000000231, RoleId=1300000000101, MenuId=1310000000331 }, new SysRoleMenu{ Id=1300000000232, RoleId=1300000000101, MenuId=1310000000332 }, new SysRoleMenu{ Id=1300000000233, RoleId=1300000000101, MenuId=1310000000333 }, @@ -161,6 +164,8 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData new SysRoleMenu{ Id=1300000001444, RoleId=1300000000101, MenuId=1310000000444 }, new SysRoleMenu{ Id=1300000001445, RoleId=1300000000101, MenuId=1310000000445 }, new SysRoleMenu{ Id=1300000001446, RoleId=1300000000101, MenuId=1310000000446 }, + // 更新日志 + new SysRoleMenu{ Id=1300000001451, RoleId=1300000000101, MenuId=1310000000451 }, ////// 日志管理 new SysRoleMenu{ Id=1300000000301, RoleId=1300000000101, MenuId=1310000000501 }, new SysRoleMenu{ Id=1300000000311, RoleId=1300000000101, MenuId=1310000000511 }, @@ -178,21 +183,20 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData new SysRoleMenu{ Id=1300000000341, RoleId=1300000000101, MenuId=1310000000541 }, new SysRoleMenu{ Id=1300000000342, RoleId=1300000000101, MenuId=1310000000542 }, new SysRoleMenu{ Id=1300000000343, RoleId=1300000000101, MenuId=1310000000543 }, + new SysRoleMenu{ Id=1300000000351, RoleId=1300000000101, MenuId=1310000000551 }, + new SysRoleMenu{ Id=1300000000352, RoleId=1300000000101, MenuId=1310000000552 }, + new SysRoleMenu{ Id=1300000000353, RoleId=1300000000101, MenuId=1310000000553 }, ////// 帮助文档 - new SysRoleMenu{ Id=1300000000401, RoleId=1300000000101, MenuId=1310000000701 }, - new SysRoleMenu{ Id=1300000000402, RoleId=1300000000101, MenuId=1310000000711 }, - new SysRoleMenu{ Id=1300000000403, RoleId=1300000000101, MenuId=1310000000712 }, - new SysRoleMenu{ Id=1300000000404, RoleId=1300000000101, MenuId=1310000000713 }, - new SysRoleMenu{ Id=1300000000405, RoleId=1300000000101, MenuId=1310000000714 }, - new SysRoleMenu{ Id=1300000000455, RoleId=1300000000101, MenuId=1310000000801 }, + new SysRoleMenu{ Id=1300000000401, RoleId=1300000000101, MenuId=1320000000101 }, + new SysRoleMenu{ Id=1300000000402, RoleId=1300000000101, MenuId=1320000000111 }, + new SysRoleMenu{ Id=1300000000403, RoleId=1300000000101, MenuId=1320000000121 }, + new SysRoleMenu{ Id=1300000000404, RoleId=1300000000101, MenuId=1320000000201 }, // 其他角色默认菜单 ////// 数据面板【1300000000102】 new SysRoleMenu{ Id=1300000000501, RoleId=1300000000102, MenuId=1300000000101 }, new SysRoleMenu{ Id=1300000000502, RoleId=1300000000102, MenuId=1300000000111 }, new SysRoleMenu{ Id=1300000000503, RoleId=1300000000102, MenuId=1300000000121 }, - // 机构管理 - new SysRoleMenu{ Id=1300000000511, RoleId=1300000000102, MenuId=1310000000142 }, // 个人中心 new SysRoleMenu{ Id=1300000000521, RoleId=1300000000102, MenuId=1310000000161 }, new SysRoleMenu{ Id=1300000000522, RoleId=1300000000102, MenuId=1310000000162 }, @@ -204,8 +208,6 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData new SysRoleMenu{ Id=1300000000601, RoleId=1300000000103, MenuId=1300000000101 }, new SysRoleMenu{ Id=1300000000602, RoleId=1300000000103, MenuId=1300000000111 }, new SysRoleMenu{ Id=1300000000603, RoleId=1300000000103, MenuId=1300000000121 }, - // 机构管理 - new SysRoleMenu{ Id=1300000000611, RoleId=1300000000103, MenuId=1310000000142 }, // 个人中心 new SysRoleMenu{ Id=1300000000621, RoleId=1300000000103, MenuId=1310000000161 }, new SysRoleMenu{ Id=1300000000622, RoleId=1300000000103, MenuId=1310000000162 }, @@ -217,8 +219,6 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData new SysRoleMenu{ Id=1300000000701, RoleId=1300000000104, MenuId=1300000000101 }, new SysRoleMenu{ Id=1300000000702, RoleId=1300000000104, MenuId=1300000000111 }, new SysRoleMenu{ Id=1300000000703, RoleId=1300000000104, MenuId=1300000000121 }, - // 机构管理 - new SysRoleMenu{ Id=1300000000711, RoleId=1300000000104, MenuId=1310000000142 }, // 个人中心 new SysRoleMenu{ Id=1300000000721, RoleId=1300000000104, MenuId=1310000000161 }, new SysRoleMenu{ Id=1300000000722, RoleId=1300000000104, MenuId=1310000000162 }, @@ -230,8 +230,6 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData new SysRoleMenu{ Id=1300000000801, RoleId=1300000000105, MenuId=1300000000101 }, new SysRoleMenu{ Id=1300000000802, RoleId=1300000000105, MenuId=1300000000111 }, new SysRoleMenu{ Id=1300000000803, RoleId=1300000000105, MenuId=1300000000121 }, - // 机构管理 - new SysRoleMenu{ Id=1300000000811, RoleId=1300000000105, MenuId=1310000000142 }, // 个人中心 new SysRoleMenu{ Id=1300000000821, RoleId=1300000000105, MenuId=1310000000161 }, new SysRoleMenu{ Id=1300000000822, RoleId=1300000000105, MenuId=1310000000162 }, diff --git a/Admin.NET/Admin.NET.Core/SeedData/SysRoleSeedData.cs b/Admin.NET/Admin.NET.Core/SeedData/SysRoleSeedData.cs index f36ef83b..7cc3861a 100644 --- a/Admin.NET/Admin.NET.Core/SeedData/SysRoleSeedData.cs +++ b/Admin.NET/Admin.NET.Core/SeedData/SysRoleSeedData.cs @@ -20,11 +20,11 @@ public class SysRoleSeedData : ISqlSugarEntitySeedData { return [ - new SysRole{ Id=1300000000101, Name="系统管理员", DataScope=DataScopeEnum.All, Code="sys_admin", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="系统管理员", TenantId=SqlSugarConst.DefaultTenantId }, - new SysRole{ Id=1300000000102, Name="本部门及以下数据", DataScope=DataScopeEnum.DeptChild, Code="sys_deptChild", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="本部门及以下数据", TenantId=SqlSugarConst.DefaultTenantId }, - new SysRole{ Id=1300000000103, Name="本部门数据", DataScope=DataScopeEnum.Dept, Code="sys_dept", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="本部门数据", TenantId=SqlSugarConst.DefaultTenantId }, - new SysRole{ Id=1300000000104, Name="仅本人数据", DataScope=DataScopeEnum.Self, Code="sys_self", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="仅本人数据", TenantId=SqlSugarConst.DefaultTenantId }, - new SysRole{ Id=1300000000105, Name="自定义数据", DataScope=DataScopeEnum.Define, Code="sys_define", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="自定义数据", TenantId=SqlSugarConst.DefaultTenantId }, + new SysRole{ Id=1300000000101, Name="系统管理员", DataScope=DataScopeEnum.All, Code="sys_admin", SysFlag=YesNoEnum.Y, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="系统管理员", TenantId=SqlSugarConst.DefaultTenantId }, + new SysRole{ Id=1300000000102, Name="本部门及以下数据", DataScope=DataScopeEnum.DeptChild, Code="sys_dept_child", SysFlag = YesNoEnum.Y, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="本部门及以下数据", TenantId=SqlSugarConst.DefaultTenantId }, + new SysRole{ Id=1300000000103, Name="本部门数据", DataScope=DataScopeEnum.Dept, Code="sys_dept", SysFlag=YesNoEnum.Y, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="本部门数据", TenantId=SqlSugarConst.DefaultTenantId }, + new SysRole{ Id=1300000000104, Name="仅本人数据", DataScope=DataScopeEnum.Self, Code="sys_self", SysFlag = YesNoEnum.Y, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="仅本人数据", TenantId=SqlSugarConst.DefaultTenantId }, + new SysRole{ Id=1300000000105, Name="自定义数据", DataScope=DataScopeEnum.Define, Code="sys_define", SysFlag = YesNoEnum.Y, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="自定义数据", TenantId=SqlSugarConst.DefaultTenantId }, ]; } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Auth/Dto/LoginUserOutput.cs b/Admin.NET/Admin.NET.Core/Service/Auth/Dto/LoginUserOutput.cs index 9e06ef51..683f8f7b 100644 --- a/Admin.NET/Admin.NET.Core/Service/Auth/Dto/LoginUserOutput.cs +++ b/Admin.NET/Admin.NET.Core/Service/Auth/Dto/LoginUserOutput.cs @@ -99,7 +99,7 @@ public class LoginUserOutput /// /// 角色集合 /// - public List RoleIds { get; set; } + public List Roles { get; set; } /// /// 水印文字 @@ -110,4 +110,25 @@ public class LoginUserOutput /// 最新密码修改时间 /// public DateTime? LastChangePasswordTime; +} + +/// +/// 角色 +/// +public class RoleDto +{ + /// + /// 角色Id + /// + public long Id { get; set; } + + /// + /// 名称 + /// + public string Name { get; set; } + + /// + /// 编码 + /// + public string Code { get; set; } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs b/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs index 30c7cd96..f6cc5729 100644 --- a/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs @@ -293,7 +293,10 @@ public class SysAuthService : IDynamicApiController, ITransient // 职位 var pos = await _sysUserRep.ChangeRepository>().GetByIdAsync(user.PosId); // 角色集合 - var roleIds = await _sysUserRep.ChangeRepository>().AsQueryable().Where(u => u.UserId == user.Id).Select(u => u.RoleId).ToListAsync(); + var roles = await _sysUserRep.ChangeRepository>().AsQueryable() + .LeftJoin((u, a) => u.RoleId == a.Id) + .Where(u => u.UserId == user.Id) + .Select((u, a) => new RoleDto { Id = a.Id, Name = a.Name, Code = a.Code }).ToListAsync(); // 接口集合 var apis = (await App.GetRequiredService().GetUserApiList())[0]; // 个性化水印文字(若系统水印为空则不显示) @@ -319,7 +322,7 @@ public class SysAuthService : IDynamicApiController, ITransient OrgType = org?.Type, PosName = pos?.Name, Apis = apis, - RoleIds = roleIds, + Roles = roles, WatermarkText = watermarkText, LastChangePasswordTime = user.LastChangePasswordTime }; @@ -341,7 +344,7 @@ public class SysAuthService : IDynamicApiController, ITransient /// 退出系统 🔖 /// [DisplayName("退出系统")] - public async void Logout() + public async Task Logout() { var httpContext = _httpContextAccessor.HttpContext ?? throw Oops.Oh(ErrorCodeEnum.D1016); diff --git a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenConfigService.cs b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenConfigService.cs index c6391581..d2eaf244 100644 --- a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenConfigService.cs +++ b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenConfigService.cs @@ -113,16 +113,8 @@ public class SysCodeGenConfigService : IDynamicApiController, ITransient 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()); - } - } + types = App.EffectiveTypes.Where(u => u.IsClass).Where(u => _codeGenOptions.EntityAssemblyNames.Contains(u.Assembly.GetName().Name) + || _codeGenOptions.EntityAssemblyNames.Any(name => u.Assembly.GetName().Name!.Contains(name))).ToList(); } Type[] cosType = types.Where(u => u.IsDefined(typeof(SugarTable), false) && !u.GetCustomAttributes().Any()).ToArray(); diff --git a/Admin.NET/Admin.NET.Core/Service/ColumnCustom/Dto/ColumnCustomInput.cs b/Admin.NET/Admin.NET.Core/Service/ColumnCustom/Dto/ColumnCustomInput.cs new file mode 100644 index 00000000..857c812d --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/ColumnCustom/Dto/ColumnCustomInput.cs @@ -0,0 +1,65 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Service; + +/// +/// 用户表格列配置基数输入参数 +/// +public class BaseColumnCustomInput +{ + /// + /// 表格Id + /// + [Required(ErrorMessage = "表格Id不能为空")] + public virtual string GridId { get; set; } +} + +/// +/// 获取用户表格列配置输入参数 +/// +public class GetColumnCustomInput : BaseColumnCustomInput +{ +} + +/// +/// 保存用户表格列配置输入参数 +/// +public class StoreColumnCustomInput +{ + /// + /// 表格Id + /// + [Required(ErrorMessage = "表格Id不能为空")] + public virtual string GridId { get; set; } + + /// + /// 冻结列状态数据 + /// + public virtual Dictionary? FixedData { get; set; } + + /// + /// 列宽状态数据 + /// + public virtual Dictionary? ResizableData { get; set; } + + /// + /// 列顺序数据 + /// + public virtual Dictionary? SortData { get; set; } + + /// + /// 显示/隐藏列状态数据 + /// + public virtual Dictionary? VisibleData { get; set; } +} + +/// +/// 重置用户表格列配置输入参数 +/// +public class ResetColumnCustomInput : BaseColumnCustomInput +{ +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/ColumnCustom/Dto/ColumnCustomOutput.cs b/Admin.NET/Admin.NET.Core/Service/ColumnCustom/Dto/ColumnCustomOutput.cs new file mode 100644 index 00000000..a4c4501c --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/ColumnCustom/Dto/ColumnCustomOutput.cs @@ -0,0 +1,43 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Service; + +/// +/// 用户表格列配置输出参数 +/// +public class ColumnCustomOutput +{ + /// + /// 用户Id + /// + public virtual long UserId { get; set; } + + /// + /// 表格Id + /// + public virtual string GridId { get; set; } + + /// + /// 冻结列状态数据 + /// + public virtual Dictionary? FixedData { get; set; } + + /// + /// 列宽状态数据 + /// + public virtual Dictionary? ResizableData { get; set; } + + /// + /// 列顺序数据 + /// + public virtual Dictionary? SortData { get; set; } + + /// + /// 显示/隐藏列状态数据 + /// + public virtual Dictionary? VisibleData { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/ColumnCustom/SysColumnCustomService.cs b/Admin.NET/Admin.NET.Core/Service/ColumnCustom/SysColumnCustomService.cs new file mode 100644 index 00000000..d22ba76b --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/ColumnCustom/SysColumnCustomService.cs @@ -0,0 +1,78 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Service; + +/// +/// 表格列配置服务 🧩 +/// +/// +/// +/// +[ApiDescriptionSettings(Order = 440, Description = "代码生成模板配置")] +public class SysColumnCustomService(SqlSugarRepository rep, UserManager um, SysCacheService cache) : IDynamicApiController, ITransient +{ + /// + /// 获取用户表格列配置信息 🔖 + /// + /// + /// + [SuppressMonitor] + [DisplayName("获取用户表格列配置信息")] + public async Task GetDetail([FromQuery] GetColumnCustomInput input) + { + var key = $"{CacheConst.KeyColumnCustom}{um.UserId}:{input.GridId}"; + var result = cache.Get(key); + if (result is null) + { + var temp = await rep.GetFirstAsync(e => e.UserId == um.UserId && e.GridId == input.GridId); + if (temp != null) + { + result = new ColumnCustomOutput + { + UserId = temp.UserId, + GridId = temp.GridId, + FixedData = string.IsNullOrEmpty(temp.FixedData) ? null : JSON.Deserialize>(temp.FixedData), + ResizableData = string.IsNullOrEmpty(temp.ResizableData) ? null : JSON.Deserialize>(temp.ResizableData), + SortData = string.IsNullOrEmpty(temp.SortData) ? null : JSON.Deserialize>(temp.SortData), + VisibleData = string.IsNullOrEmpty(temp.VisibleData) ? null : JSON.Deserialize>(temp.VisibleData), + }; + cache.Set(key, result, TimeSpan.FromDays(7)); + } + } + return result; + } + + /// + /// 保存用户表格列配置信息 🔖 + /// + /// + /// + [DisplayName("保存用户表格列配置信息")] + public async Task Store(StoreColumnCustomInput input) + { + var temp = await rep.GetFirstAsync(e => e.UserId == um.UserId && e.GridId == input.GridId); + if (temp is null) temp = new SysColumnCustom { UserId = um.UserId, GridId = input.GridId }; + else cache.Remove($"{CacheConst.KeyColumnCustom}{um.UserId}:{input.GridId}"); // 移除缓存 + temp.FixedData = JSON.Serialize(input.FixedData); + temp.ResizableData = JSON.Serialize(input.ResizableData); + temp.SortData = JSON.Serialize(input.SortData); + temp.VisibleData = JSON.Serialize(input.VisibleData); + await rep.Context.Storageable(temp).ExecuteCommandAsync(); + } + + /// + /// 清除用户表格列配置信息 🔖 + /// + /// + /// + [DisplayName("清除用户表格列配置信息")] + public async Task Reset(ResetColumnCustomInput input) + { + await rep.AsDeleteable().Where(e => e.UserId == um.UserId && e.GridId == input.GridId).ExecuteCommandAsync(); + cache.Remove($"{CacheConst.KeyColumnCustom}{um.UserId}:{input.GridId}"); // 移除缓存 + } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs b/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs index 67b574e1..473e2e71 100644 --- a/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs @@ -278,11 +278,11 @@ public class SysCommonService : IDynamicApiController, ITransient var stressTestHarnessResult = await _httpRemoteService.SendAsync(HttpRequestBuilder.StressTestHarness(input.RequestUri) .SetNumberOfRequests(input.NumberOfRequests) // 并发请求数量 .SetNumberOfRounds(input.NumberOfRounds) // 压测轮次 - .SetMaxDegreeOfParallelism(input.MaxDegreeOfParallelism), // 最大并发度 - builder => builder.WithHeaders(input.Headers) - .WithQueryParameters(input.QueryParameters) - .WithPathParameters(input.PathParameters) - .SetJsonContent(input.JsonContent)); + .SetMaxDegreeOfParallelism(input.MaxDegreeOfParallelism) // 最大并发度 + .WithRequest(builder => builder.WithHeaders(input.Headers) + .WithQueryParameters(input.QueryParameters) + .WithPathParameters(input.PathParameters) + .SetJsonContent(input.JsonContent))); return stressTestHarnessResult; } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Dict/SysDictDataService.cs b/Admin.NET/Admin.NET.Core/Service/Dict/SysDictDataService.cs index 976ccb49..0a81647c 100644 --- a/Admin.NET/Admin.NET.Core/Service/Dict/SysDictDataService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Dict/SysDictDataService.cs @@ -15,7 +15,6 @@ public class SysDictDataService : IDynamicApiController, ITransient private readonly SqlSugarRepository _sysDictDataRep; private readonly SysCacheService _sysCacheService; private readonly UserManager _userManager; - public readonly ISugarQueryable VSysDictData; public SysDictDataService(SqlSugarRepository sysDictDataRep, SysCacheService sysCacheService, @@ -24,9 +23,6 @@ public class SysDictDataService : IDynamicApiController, ITransient _sysDictDataRep = sysDictDataRep; _sysCacheService = sysCacheService; _userManager = userManager; - VSysDictData = _sysDictDataRep.Context.UnionAll( - _sysDictDataRep.AsQueryable(), - _sysDictDataRep.Change().AsQueryable().Select()); } /// @@ -37,7 +33,7 @@ public class SysDictDataService : IDynamicApiController, ITransient [DisplayName("获取字典值分页列表")] public async Task> Page(PageDictDataInput input) { - return await VSysDictData + return await _sysDictDataRep.AsQueryable() .Where(u => u.DictTypeId == input.DictTypeId) .WhereIF(!string.IsNullOrEmpty(input.Code?.Trim()), u => u.Code.Contains(input.Code)) .WhereIF(!string.IsNullOrEmpty(input.Label?.Trim()), u => u.Label.Contains(input.Label)) @@ -64,7 +60,7 @@ public class SysDictDataService : IDynamicApiController, ITransient [DisplayName("增加字典值")] public async Task AddDictData(AddDictDataInput input) { - var isExist = await VSysDictData.AnyAsync(u => u.Code == input.Code && u.DictTypeId == input.DictTypeId); + var isExist = await _sysDictDataRep.IsAnyAsync(u => u.Code == input.Code && u.DictTypeId == input.DictTypeId); if (isExist) throw Oops.Oh(ErrorCodeEnum.D3003); var dictType = await _sysDictDataRep.Change().GetByIdAsync(input.DictTypeId); @@ -72,7 +68,7 @@ public class SysDictDataService : IDynamicApiController, ITransient _sysCacheService.Remove($"{CacheConst.KeyDict}{dictType.Code}"); - dynamic dictData = dictType.IsTenant == YesNoEnum.Y ? input.Adapt() : input.Adapt(); + var dictData = dictType.IsTenant == YesNoEnum.Y ? input.Adapt() : input.Adapt(); await _sysDictDataRep.Context.Insertable(dictData).ExecuteCommandAsync(); } @@ -86,17 +82,17 @@ public class SysDictDataService : IDynamicApiController, ITransient [DisplayName("更新字典值")] public async Task UpdateDictData(UpdateDictDataInput input) { - var isExist = await VSysDictData.AnyAsync(u => u.Id == input.Id); + var isExist = await _sysDictDataRep.IsAnyAsync(u => u.Id == input.Id); if (!isExist) throw Oops.Oh(ErrorCodeEnum.D3004); - isExist = await VSysDictData.AnyAsync(u => u.Code == input.Code && u.DictTypeId == input.DictTypeId && u.Id != input.Id); + isExist = await _sysDictDataRep.IsAnyAsync(u => u.Code == input.Code && u.DictTypeId == input.DictTypeId && u.Id != input.Id); if (isExist) throw Oops.Oh(ErrorCodeEnum.D3003); var dictType = await _sysDictDataRep.Change().GetByIdAsync(input.DictTypeId); if (dictType.SysFlag == YesNoEnum.Y && !_userManager.SuperAdmin) throw Oops.Oh(ErrorCodeEnum.D3009); _sysCacheService.Remove($"{CacheConst.KeyDict}{dictType.Code}"); - dynamic dictData = dictType.IsTenant == YesNoEnum.Y ? input.Adapt() : input.Adapt(); + var dictData = dictType.IsTenant == YesNoEnum.Y ? input.Adapt() : input.Adapt(); await _sysDictDataRep.Context.Updateable(dictData).ExecuteCommandAsync(); } @@ -110,13 +106,13 @@ public class SysDictDataService : IDynamicApiController, ITransient [DisplayName("删除字典值")] public async Task DeleteDictData(DeleteDictDataInput input) { - var dictData = await VSysDictData.FirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D3004); + var dictData = await _sysDictDataRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D3004); var dictType = await _sysDictDataRep.Change().GetByIdAsync(dictData.DictTypeId); if (dictType.SysFlag == YesNoEnum.Y && !_userManager.SuperAdmin) throw Oops.Oh(ErrorCodeEnum.D3010); _sysCacheService.Remove($"{CacheConst.KeyDict}{dictType.Code}"); - dynamic entity = dictType.IsTenant == YesNoEnum.Y ? input.Adapt() : input.Adapt(); + var entity = dictType.IsTenant == YesNoEnum.Y ? input.Adapt() : input.Adapt(); await _sysDictDataRep.Context.Deleteable(entity).ExecuteCommandAsync(); } @@ -128,7 +124,7 @@ public class SysDictDataService : IDynamicApiController, ITransient [DisplayName("获取字典值详情")] public async Task GetDetail([FromQuery] DictDataInput input) { - return (await VSysDictData.FirstAsync(u => u.Id == input.Id))?.Adapt(); + return await _sysDictDataRep.GetByIdAsync(input.Id); } /// @@ -140,7 +136,7 @@ public class SysDictDataService : IDynamicApiController, ITransient [DisplayName("修改字典值状态")] public async Task SetStatus(DictDataInput input) { - var dictData = await VSysDictData.FirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D3004); + var dictData = await _sysDictDataRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D3004); var dictType = await _sysDictDataRep.Change().GetByIdAsync(dictData.DictTypeId); if (dictType.SysFlag == YesNoEnum.Y && !_userManager.SuperAdmin) throw Oops.Oh(ErrorCodeEnum.D3009); @@ -148,7 +144,7 @@ public class SysDictDataService : IDynamicApiController, ITransient _sysCacheService.Remove($"{CacheConst.KeyDict}{dictType.Code}"); dictData.Status = input.Status; - dynamic entity = dictType.IsTenant == YesNoEnum.Y ? input.Adapt() : input.Adapt(); + var entity = dictType.IsTenant == YesNoEnum.Y ? input.Adapt() : input.Adapt(); await _sysDictDataRep.Context.Updateable(entity).ExecuteCommandAsync(); } @@ -187,26 +183,42 @@ public class SysDictDataService : IDynamicApiController, ITransient !string.IsNullOrWhiteSpace(code) && typeId != null) throw Oops.Oh(ErrorCodeEnum.D3011); - var dictType = await _sysDictDataRep.Change().AsQueryable() - .WhereIF(!string.IsNullOrWhiteSpace(code), u => u.Code == code) - .WhereIF(typeId != null, u => u.Id == typeId) - .FirstAsync(); - if (dictType == null) return null; - - var dictDataList = _sysCacheService.Get>($"{CacheConst.KeyDict}{dictType.Code}"); + var dictDataList = _sysCacheService.Get>($"{CacheConst.KeyDict}{code}"); if (dictDataList == null) { - dictDataList = await VSysDictData.InnerJoin((u, a) => u.DictTypeId == a.Id) - .Where(u => u.DictTypeId == dictType.Id) - .Select((u, a) => new SysDictData - { - Status = u.Status == StatusEnum.Enable && a.Status == StatusEnum.Enable ? StatusEnum.Enable : StatusEnum.Disable, - }, true) - .OrderBy(u => new { u.OrderNo, u.Code }) - .ToListAsync(); - _sysCacheService.Set($"{CacheConst.KeyDict}{dictType.Code}", dictDataList); + dictDataList = await _sysDictDataRep.Change().AsQueryable() + .LeftJoin((u, a) => u.Id == a.DictTypeId).ClearFilter() + .WhereIF(!string.IsNullOrWhiteSpace(code), u => u.Code == code) + .WhereIF(typeId != null && typeId > 0, u => u.Id == typeId) + .Where((u, a) => u.Status == StatusEnum.Enable && a.Status == StatusEnum.Enable) + .OrderBy((u, a) => new { a.OrderNo, a.Code }) + .Select((u, a) => a).ToListAsync(); + _sysCacheService.Set($"{CacheConst.KeyDict}{code}", dictDataList); } return dictDataList; + + //// 判断字典是否存在 + //var dictType = await _sysDictDataRep.Change().AsQueryable() + // .WhereIF(!string.IsNullOrWhiteSpace(code), u => u.Code == code) + // .WhereIF(typeId != null, u => u.Id == typeId) + // .FirstAsync(); + //if (dictType == null) return null; + + //var dictDataList = _sysCacheService.Get>($"{CacheConst.KeyDict}{dictType.Code}"); + //if (dictDataList == null) + //{ + // dictDataList = await _sysDictDataRep.AsQueryable() + // .InnerJoin((u, a) => u.DictTypeId == a.Id) + // .Where(u => u.DictTypeId == dictType.Id) + // .Select((u, a) => new SysDictData + // { + // Status = u.Status == StatusEnum.Enable && a.Status == StatusEnum.Enable ? StatusEnum.Enable : StatusEnum.Disable, + // }, true) + // .OrderBy(u => new { u.OrderNo, u.Code }) + // .ToListAsync(); + // _sysCacheService.Set($"{CacheConst.KeyDict}{dictType.Code}", dictDataList); + //} + //return dictDataList; } /// diff --git a/Admin.NET/Admin.NET.Core/Service/Dict/SysDictTypeService.cs b/Admin.NET/Admin.NET.Core/Service/Dict/SysDictTypeService.cs index 3f012bc1..ed840fb1 100644 --- a/Admin.NET/Admin.NET.Core/Service/Dict/SysDictTypeService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Dict/SysDictTypeService.cs @@ -163,7 +163,7 @@ public class SysDictTypeService : IDynamicApiController, ITransient public async Task GetAllDictList() { var ds = await _sysDictTypeRep.AsQueryable() - .InnerJoin(_sysDictDataService.VSysDictData, (u, a) => u.Id == a.DictTypeId) + .InnerJoin((u, a) => u.Id == a.DictTypeId).ClearFilter() .Where((u, a) => u.Status == StatusEnum.Enable && a.Status == StatusEnum.Enable) .Select((u, a) => new { TypeCode = u.Code, a.Label, a.Value, a.Code, a.Remark, a.OrderNo, a.TagType, a.ExtData }) .ToListAsync(); diff --git a/Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs b/Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs index 3bfb7780..827bcc83 100644 --- a/Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs +++ b/Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs @@ -4,7 +4,6 @@ // // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! -using Aliyun.OSS.Util; using Furion.AspNetCore; using Microsoft.AspNetCore.Mvc.ModelBinding; @@ -43,7 +42,7 @@ public class SysFileService : IDynamicApiController, ITransient { _customFileProvider = _namedServiceProvider.GetService(nameof(SSHFileProvider)); } - else if (App.Configuration["Upload:EnableSaveFileToDb"].ToBoolean()) + else if (_uploadOptions.EnableSaveDb) { _customFileProvider = _namedServiceProvider.GetService(nameof(DbFileProvider)); } @@ -138,6 +137,7 @@ public class SysFileService : IDynamicApiController, ITransient /// [HttpGet("/upload/downloadfile")] [DisplayName("根据文件Id和MD5下载")] + [AllowAnonymous] public async Task DownloadFile2([FromQuery] long id, [FromQuery] string fileMd5) { var file = await GetFile(id); @@ -269,10 +269,12 @@ public class SysFileService : IDynamicApiController, ITransient // 判断是否重复上传的文件 var sizeKb = input.File.Length / 1024; // 大小KB var fileMd5 = string.Empty; - // 不管要不要验证md5,也把Md6计算出来,方便统计重复的文件。 + // 计算文件MD5(长度为32的固定字符串) await using (var fileStream = input.File.OpenReadStream()) { - fileMd5 = OssUtils.ComputeContentMd5(fileStream, fileStream.Length); + byte[] bsFile = new byte[fileStream.Length]; + _ = fileStream.Read(bsFile, 0, bsFile.Length); + fileMd5 = MD5Encryption.Encrypt(bsFile); } if (_uploadOptions.EnableMd5) { @@ -409,5 +411,19 @@ public class SysFileService : IDynamicApiController, ITransient await _sysFileRep.AsDeleteable().Where(u => u.DataId == dataId).ExecuteCommandAsync(); } + /// + /// 根据业务数据Id获取文件列表 + /// + /// + /// + /// + [NonAction] + public async Task> GetFileListByDataId([FromQuery] long dataId, [FromQuery] bool isClearFilter = false) + { + return isClearFilter + ? await _sysFileRep.CopyNew().AsQueryable().ClearFilter().Where(u => u.DataId == dataId).ToListAsync() + : await _sysFileRep.CopyNew().GetListAsync(u => u.DataId == dataId); + } + #endregion 统一实体与文件关联时,业务应用实体只需要定义一个SysFile集合导航属性,业务增加和更新、删除分别调用即可 } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Job/JobClusterServer.cs b/Admin.NET/Admin.NET.Core/Service/Job/JobClusterServer.cs index 59a6ddd7..2a88db5c 100644 --- a/Admin.NET/Admin.NET.Core/Service/Job/JobClusterServer.cs +++ b/Admin.NET/Admin.NET.Core/Service/Job/JobClusterServer.cs @@ -23,19 +23,19 @@ public class JobClusterServer : IJobClusterServer /// 当前作业调度器启动通知 /// /// 作业集群服务上下文 - public async void Start(JobClusterContext context) + public void Start(JobClusterContext context) { using var scope = _serviceScopeFactory.CreateScope(); var db = scope.ServiceProvider.GetRequiredService().CopyNew(); // 在作业集群表中,如果 clusterId 不存在,则新增一条(否则更新一条),并设置 status 为 ClusterStatus.Waiting - if (await db.Queryable().AnyAsync(u => u.ClusterId == context.ClusterId)) + if (db.Queryable().Any(u => u.ClusterId == context.ClusterId)) { - await db.Updateable().SetColumns(u => u.Status == ClusterStatus.Waiting).Where(u => u.ClusterId == context.ClusterId).ExecuteCommandAsync(); + db.Updateable().SetColumns(u => u.Status == ClusterStatus.Waiting).Where(u => u.ClusterId == context.ClusterId).ExecuteCommand(); } else { - await db.Insertable(new SysJobCluster { ClusterId = context.ClusterId, Status = ClusterStatus.Waiting }).ExecuteCommandAsync(); + db.Insertable(new SysJobCluster { ClusterId = context.ClusterId, Status = ClusterStatus.Waiting }).ExecuteCommand(); } } @@ -72,7 +72,9 @@ public class JobClusterServer : IJobClusterServer return; } } - catch { } + catch + { + } } } @@ -80,24 +82,24 @@ public class JobClusterServer : IJobClusterServer /// 当前作业调度器停止通知 /// /// 作业集群服务上下文 - public async void Stop(JobClusterContext context) + public void Stop(JobClusterContext context) { // 在作业集群表中,更新 clusterId 的 status 为 ClusterStatus.Crashed using var scope = _serviceScopeFactory.CreateScope(); var db = scope.ServiceProvider.GetRequiredService().CopyNew(); - await db.Updateable(new SysJobCluster { Status = ClusterStatus.Crashed }).Where(u => u.ClusterId == context.ClusterId).ExecuteCommandAsync(); + db.Updateable(new SysJobCluster { Status = ClusterStatus.Crashed }).Where(u => u.ClusterId == context.ClusterId).ExecuteCommand(); } /// /// 当前作业调度器宕机 /// /// 作业集群服务上下文 - public async void Crash(JobClusterContext context) + public void Crash(JobClusterContext context) { // 在作业集群表中,更新 clusterId 的 status 为 ClusterStatus.Crashed using var scope = _serviceScopeFactory.CreateScope(); var db = scope.ServiceProvider.GetRequiredService().CopyNew(); - await db.Updateable(new SysJobCluster { Status = ClusterStatus.Crashed }).Where(u => u.ClusterId == context.ClusterId).ExecuteCommandAsync(); + db.Updateable(new SysJobCluster { Status = ClusterStatus.Crashed }).Where(u => u.ClusterId == context.ClusterId).ExecuteCommand(); } /// diff --git a/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportConfigInput.cs b/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportConfigInput.cs new file mode 100644 index 00000000..5392ec20 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportConfigInput.cs @@ -0,0 +1,63 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 报表配置分页输入参数 +/// +public class PageReportConfigInput : BasePageInput +{ + /// + /// 名称 + /// + public string Name { get; set; } + + /// + /// 分组Id + /// + public long? GroupId { get; set; } +} + +public class AddReportConfigInput : SysReportConfig +{ +} + +public class UpdateReportConfigInput : SysReportConfig +{ +} + +/// +/// 报表配置解析Sql输入参数 +/// +public class ReportConfigParseSqlInput +{ + /// + /// 数据源 + /// + public string DataSource { get; set; } + + /// + /// 脚本语句 + /// + public string SqlScript { get; set; } + + /// + /// 执行参数 + /// + public Dictionary ExecParams { get; set; } = []; +} + +/// +/// 报表配置执行Sql脚本输入参数 +/// +public class ReportConfigExecuteSqlScriptInput : BaseIdInput +{ + /// + /// 执行参数 + /// + public Dictionary ExecParams { get; set; } = []; +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportConfigOutput.cs b/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportConfigOutput.cs new file mode 100644 index 00000000..fa19666f --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportConfigOutput.cs @@ -0,0 +1,32 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +using Newtonsoft.Json; + +namespace Admin.NET.Core; + +/// +/// 报表配置输出参数 +/// +public class ReportConfigOutput : SysReportConfig +{ + /// + /// 分组名称 + /// + public string GroupName { get; set; } +} + +/// +/// 报表配置解析Sql输出参数 +/// +public class ReportConfigParseSqlOutput +{ + /// + /// 报表字段名称集合 + /// + [JsonConverter(typeof(CamelCaseValueConverter))] + public List FieldNames { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportDataSourceDetail.cs b/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportDataSourceDetail.cs new file mode 100644 index 00000000..7b01e33d --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportDataSourceDetail.cs @@ -0,0 +1,38 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 报表数据源详情 +/// +public class SysReportDataSourceDetail +{ + /// + /// Id + /// + public string Id { get; set; } + + /// + /// 名称 + /// + public string Name { get; set; } + + /// + /// 是否内置 + /// + public bool IsBuildIn { get; set; } + + /// + /// 数据库类型 + /// + public SqlSugar.DbType DbType { get; set; } + + /// + /// 连接字符串 + /// + public string ConnectionString { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportDataSourceInput.cs b/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportDataSourceInput.cs new file mode 100644 index 00000000..b9ca98b9 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportDataSourceInput.cs @@ -0,0 +1,26 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 报表数据源分页输入参数 +/// +public class PageReportDataSourceInput : BasePageInput +{ + /// + /// 名称 + /// + public string Name { get; set; } +} + +public class AddReportDataSourceInput : SysReportDataSource +{ +} + +public class UpdateReportDataSourceInput : SysReportDataSource +{ +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportDataSourceOutput.cs b/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportDataSourceOutput.cs new file mode 100644 index 00000000..ccd957d4 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportDataSourceOutput.cs @@ -0,0 +1,28 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 报表数据源输出参数 +/// +public class ReportDataSourceOutput +{ + /// + /// Id + /// + public string Id { get; set; } + + /// + /// 名称 + /// + public string Name { get; set; } + + /// + /// 是否内置 + /// + public bool IsBuildIn { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportGroupInput.cs b/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportGroupInput.cs new file mode 100644 index 00000000..e25c2580 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportGroupInput.cs @@ -0,0 +1,26 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 报表分组分页输入参数 +/// +public class PageReportGroupInput : BasePageInput +{ + /// + /// 名称 + /// + public string Name { get; set; } +} + +public class AddReportGroupInput : SysReportGroup +{ +} + +public class UpdateReportGroupInput : SysReportGroup +{ +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportLayoutConfig.cs b/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportLayoutConfig.cs new file mode 100644 index 00000000..a2dd5c3a --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/ReportConfig/Dto/SysReportLayoutConfig.cs @@ -0,0 +1,89 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +using Newtonsoft.Json; + +namespace Admin.NET.Core; + +/// +/// 报表布局配置 +/// +public class SysReportLayoutConfig +{ + /// + /// 报表字段集合 + /// + public List Fields { get; set; } + + /// + /// 报表参数集合 + /// + public List Params { get; set; } +} + +/// +/// 报表字段 +/// +public class SysReportField +{ + /// + /// 字段名 + /// + [JsonConverter(typeof(CamelCaseValueConverter))] + public string FieldName { get; set; } + + /// + /// 字段标题 + /// + public string Title { get; set; } + + /// + /// 是否合计 + /// + public bool IsSummary { get; set; } + + /// + /// 是否显示 + /// + public bool Visible { get; set; } + + /// + /// 分组标题 + /// + public string GroupTitle { get; set; } + + /// + /// 列宽度 + /// + public int Width { get; set; } +} + +/// +/// 报表参数 +/// +public class SysReportParam +{ + /// + /// 参数名 + /// + [JsonConverter(typeof(CamelCaseValueConverter))] + public string ParamName { get; set; } + + /// + /// 参数标题 + /// + public string Title { get; set; } + + /// + /// 输入控件类型 + /// + public string InputCtrl { get; set; } + + /// + /// 默认值 + /// + public object DefaultValue { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/ReportConfig/SysReportConfigService.cs b/Admin.NET/Admin.NET.Core/Service/ReportConfig/SysReportConfigService.cs new file mode 100644 index 00000000..d600f715 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/ReportConfig/SysReportConfigService.cs @@ -0,0 +1,426 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +using OfficeOpenXml; + +namespace Admin.NET.Core.Service; + +/// +/// 系统报表配置服务 +/// +[ApiDescriptionSettings(Order = 500, Description = "报表配置")] +public class SysReportConfigService : IDynamicApiController, ITransient +{ + private readonly SqlSugarRepository _reportConfigRep; + private readonly SysReportDataSourceService _sysReportDataSourceService; + private readonly SysTenantService _sysTenantService; + private readonly UserManager _userManager; + + public SysReportConfigService(SqlSugarRepository reportConfigRep, + SysReportDataSourceService sysReportDataSourceService, + SysTenantService sysTenantService, + UserManager userManager + ) + { + _reportConfigRep = reportConfigRep; + _sysReportDataSourceService = sysReportDataSourceService; + _sysTenantService = sysTenantService; + _userManager = userManager; + } + + /// + /// 获取报表配置分页列表 + /// + /// + /// + [DisplayName("获取报表配置分页列表")] + public async Task> Page(PageReportConfigInput input) + { + return await _reportConfigRep.AsQueryable() + .LeftJoin((u, a) => u.GroupId == a.Id) + .WhereIF(!string.IsNullOrWhiteSpace(input.Name), (u, a) => u.Name.Contains(input.Name.Trim())) + .WhereIF(input.GroupId is > 0, (u, a) => u.GroupId == input.GroupId) + .Select((u, a) => new ReportConfigOutput + { + GroupName = a.Name + }, true) + .OrderBuilder(input, "u.") + .ToPagedListAsync(input.Page, input.PageSize); + } + + /// + /// 增加报表配置 + /// + /// + /// + [ApiDescriptionSettings(Name = "Add"), HttpPost] + [DisplayName("增加报表配置")] + public async Task Add(AddReportConfigInput input) + { + var isExist = await _reportConfigRep.IsAnyAsync(u => u.Name == input.Name && u.Id != input.Id); + if (isExist) + throw Oops.Bah(ErrorCodeEnum.C1000); + + await _reportConfigRep.InsertAsync(input.Adapt()); + } + + /// + /// 更新报表配置 + /// + /// + /// + [UnitOfWork] + [ApiDescriptionSettings(Name = "Update"), HttpPost] + [DisplayName("更新报表配置")] + public async Task Update(UpdateReportConfigInput input) + { + var isExist = await _reportConfigRep.IsAnyAsync(u => u.Name == input.Name && u.Id != input.Id); + if (isExist) + throw Oops.Bah(ErrorCodeEnum.C1000); + + await _reportConfigRep.UpdateAsync(input.Adapt()); + } + + /// + /// 删除报表配置 + /// + /// + /// + [UnitOfWork] + [ApiDescriptionSettings(Name = "Delete"), HttpPost] + [DisplayName("删除报表配置")] + public async Task Delete(BaseIdInput input) + { + await _reportConfigRep.DeleteAsync(u => u.Id == input.Id); + } + + /// + /// 复制报表配置 + /// + /// + /// + [UnitOfWork] + [ApiDescriptionSettings(Name = "Copy"), HttpPost] + [DisplayName("复制报表配置")] + public async Task Copy(BaseIdInput input) + { + var entity = await _reportConfigRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Bah(ErrorCodeEnum.D1002); + entity.Id = YitIdHelper.NextId(); + entity.Name = $"{entity.Name} - 副本"; + entity.CreateTime = DateTime.Now; + entity.CreateUserId = null; + entity.CreateUserName = null; + entity.UpdateTime = null; + entity.UpdateUserId = null; + entity.UpdateUserName = null; + + await Add(entity.Adapt()); + } + + /// + /// 获取报表布局配置 + /// + /// 输入参数 + [ApiDescriptionSettings(Name = "GetLayoutConfig"), HttpGet] + [DisplayName("获取报表布局配置")] + public SysReportLayoutConfig GetLayoutConfig([FromQuery] BaseIdInput input) + { + var entity = _reportConfigRep.GetFirst(u => u.Id == input.Id); + return entity == null + ? throw Oops.Bah(ErrorCodeEnum.D1002) + : new SysReportLayoutConfig + { + Fields = string.IsNullOrEmpty(entity.Fields) ? [] : JSON.Deserialize>(entity.Fields), + Params = string.IsNullOrEmpty(entity.Params) ? [] : JSON.Deserialize>(entity.Params), + }; + } + + /// + /// 解析报表配置Sql + /// + /// 输入参数 + [ApiDescriptionSettings(Name = "ParseSql"), HttpPost] + [DisplayName("解析报表配置Sql")] + public async Task ParseSql(ReportConfigParseSqlInput input) + { + var dataTable = await InnerExecuteSqlScript(input.DataSource, input.SqlScript, input.ExecParams); + var fieldNames = (from DataColumn column in dataTable.Columns select column.ColumnName).ToList(); + + return new ReportConfigParseSqlOutput + { + FieldNames = fieldNames + }; + } + + /// + /// 执行报表配置Sql脚本 + /// + /// 输入参数 + [ApiDescriptionSettings(Name = "ExecuteSqlScript"), HttpPost] + [DisplayName("执行报表配置Sql脚本")] + // 指定使用 CamelCaseDictionaryKey 的序列化配置选项,使字典的 Key 转换为驼峰样式 + [UnifySerializerSetting("CamelCaseDictionaryKey")] + public async Task>> ExecuteSqlScript(ReportConfigExecuteSqlScriptInput input) + { + var entity = await _reportConfigRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Bah(ErrorCodeEnum.D1002); + if (entity.DsType != ReportConfigDsTypeEnum.Sql) + throw Oops.Bah(ErrorCodeEnum.C1001); + + var layoutConfig = GetLayoutConfig(input); + var execParams = new Dictionary(input.ExecParams); + // 补充没有传入的参数,如果传入 null,则填充空字符串,不为 null sqlsugar 才会构造参数 + foreach (var param in layoutConfig.Params) + { + execParams.TryAdd(param.ParamName, ""); + execParams[param.ParamName] ??= ""; + } + + var dataTable = await InnerExecuteSqlScript(entity.DataSource, entity.SqlScript, execParams); + + // 处理汇总字段 + var summaryFieldNames = layoutConfig.Fields.Where(u => u.IsSummary).Select(u => u.FieldName).ToList(); + if (summaryFieldNames.Count > 0) + { + var summaryInfo = new Dictionary(); + UnifyContext.Fill(summaryInfo); + foreach (var summaryFieldName in summaryFieldNames) + { + summaryInfo[summaryFieldName] = dataTable.AsEnumerable().Sum(row => + { + decimal.TryParse(row[summaryFieldName] + "", out decimal summaryValue); + return summaryValue; + }); + } + } + + return dataTable.AsEnumerable().Select(UtilMethods.DataRowToDictionary).ToList(); + } + + /// + /// 执行Sql脚本内部实现 + /// + /// + /// + /// + /// + private async Task InnerExecuteSqlScript(string dataSource, string sqlScript, Dictionary execParams) + { + var isSelectQuery = IsSelectQuery(sqlScript); + + var dataSourceDetailList = await _sysReportDataSourceService.GetDataSourceListIncludeDetail(); + var dataSourceDetail = dataSourceDetailList.FirstOrDefault(u => u.Id == dataSource) ?? throw Oops.Bah(ErrorCodeEnum.C1002); + ISqlSugarClient dbClient = GetDbClient(dataSourceDetail); + + var newExecParams = BuildInParamsHandle(dbClient, sqlScript, execParams); + var parameters = newExecParams.Select(u => new SugarParameter(u.Key, u.Value)).ToList(); + + if (isSelectQuery) + { + // SELECT 查询 + var dataTable = await dbClient.Ado.GetDataTableAsync(sqlScript, parameters); + return dataTable; + } + else + { + // 存储过程 + var dataTable = await dbClient.Ado.UseStoredProcedure().GetDataTableAsync(sqlScript, parameters); + return dataTable; + } + } + + /// + /// 获取 DbClient + /// + /// + /// + private ISqlSugarClient GetDbClient(SysReportDataSourceDetail dataSourceDetail) + { + ISqlSugarClient dbClient = null; + if (dataSourceDetail.IsBuildIn) + { + // 获取内置数据库和租户的连接 + dbClient = _sysTenantService.GetTenantDbConnectionScope(long.Parse(dataSourceDetail.Id)); + } + else + { + if (SqlSugarSetup.ITenant.IsAnyConnection(dataSourceDetail.Id)) + { + dbClient = SqlSugarSetup.ITenant.GetConnectionScope(dataSourceDetail.Id); + } + + // dbClient 不存在或者连接字符串不一样,则重新设置 + if (dbClient == null || dbClient.CurrentConnectionConfig.ConnectionString != dataSourceDetail.ConnectionString) + { + // 获取默认库连接配置 + var dbOptions = App.GetOptions(); + var mainConnConfig = dbOptions.ConnectionConfigs.First(u => u.ConfigId.ToString() == SqlSugarConst.MainConfigId); + + // 设置连接配置 + var tenantConnConfig = new DbConnectionConfig + { + ConfigId = dataSourceDetail.Id, + DbType = dataSourceDetail.DbType, + IsAutoCloseConnection = true, + ConnectionString = dataSourceDetail.ConnectionString, + DbSettings = new DbSettings + { + EnableUnderLine = mainConnConfig.DbSettings.EnableUnderLine, + }, + }; + SqlSugarSetup.ITenant.AddConnection(tenantConnConfig); + dbClient = SqlSugarSetup.ITenant.GetConnectionScope(dataSourceDetail.Id); + } + } + + return dbClient; + } + + /// + /// 内置参数处理 + /// + private Dictionary BuildInParamsHandle(ISqlSugarClient dbClient, string sqlScript, Dictionary execParams) + { + var newExecParams = new Dictionary(execParams); + + if (sqlScript.IndexOf("@curTenantId", StringComparison.Ordinal) > -1) newExecParams["@curTenantId"] = _userManager.TenantId; + if (sqlScript.IndexOf("@curUserId", StringComparison.Ordinal) > -1) newExecParams["@curUserId"] = _userManager.UserId; + + return newExecParams; + } + + private static bool IsSelectQuery(string sqlScript) + { + // 使用正则表达式判断是否包含 SELECT 关键字(忽略大小写) + var pattern = @"\bselect\b"; + var isSelectQuery = Regex.IsMatch(sqlScript, pattern, RegexOptions.IgnoreCase); + + return isSelectQuery; + } + + /// + /// 导出报表到Excel + /// + /// + /// + /// + [ApiDescriptionSettings(Name = "ExportToExcel"), HttpPost] + [DisplayName("导出报表到Excel")] + public async Task ExportToExcel(ReportConfigExecuteSqlScriptInput input) + { + var entity = await _reportConfigRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Bah(ErrorCodeEnum.D1002); + + // 执行Sql脚本 + var data = await ExecuteSqlScript(input); + // 重新创建忽略大小写的字典 + data = data.Select(u => new Dictionary(u, StringComparer.OrdinalIgnoreCase)).ToList(); + + var layoutConfig = GetLayoutConfig(input); + var fields = layoutConfig.Fields.Where(f => f.Visible).ToList(); + + // 按字段原始顺序处理分组 + var orderedGroups = OrderedGroupFields(fields); + + using var package = new ExcelPackage(); + var worksheet = package.Workbook.Worksheets.Add("ReportData"); + + int currentRow = 1; + int startCol = 1; + if (orderedGroups.Any(u => u.Any(p => !string.IsNullOrEmpty(p.GroupTitle)))) + { + foreach (var group in orderedGroups) + { + int colCount = group.Count(); + worksheet.Cells[currentRow, startCol, currentRow, startCol + colCount - 1].Merge = true; + worksheet.Cells[currentRow, startCol].Value = group.First().GroupTitle; + startCol += colCount; + } + + currentRow++; + } + + // 处理列标题(使用Title或FieldName) + var curColIndex = 0; + foreach (var field in orderedGroups.SelectMany(group => group)) + { + worksheet.Cells[currentRow, curColIndex + 1].Value = string.IsNullOrEmpty(field.Title) ? field.FieldName : field.Title; + curColIndex++; + } + + currentRow++; + + // 填充数据 + foreach (var item in data) + { + curColIndex = 0; + foreach (var field in orderedGroups.SelectMany(group => group)) + { + worksheet.Cells[currentRow, curColIndex + 1].Value = item[field.FieldName]; + curColIndex++; + } + + currentRow++; + } + + // 处理汇总行 + var summaryFields = fields.Where(f => f.IsSummary).ToList(); + if (summaryFields.Count > 0) + { + worksheet.Cells[currentRow, 1].Value = "汇总"; + foreach (var field in summaryFields) + { + int colIndex = fields.FindIndex(f => f.FieldName == field.FieldName) + 1; + decimal sum = data.Sum(r => + { + decimal.TryParse(r[field.FieldName]?.ToString(), out decimal val); + return val; + }); + worksheet.Cells[currentRow, colIndex].Value = sum; + } + + currentRow++; + } + + // 自动调整列宽 + worksheet.Cells[1, 1, currentRow - 1, fields.Count].AutoFitColumns(); + + var stream = new MemoryStream(); + package.SaveAs(stream); + stream.Position = 0; + + var fileName = entity.Name + $"_{DateTime.Now:yyyyMMddHHmmss}.xlsx"; + return new FileStreamResult(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") { FileDownloadName = fileName }; + } + + /// + /// 按照字段原始顺序处理分组 + /// + private List> OrderedGroupFields(List fields) + { + // GroupTitle 没有值,填充特定值作为独自分组 + foreach (var field in fields.Where(field => string.IsNullOrWhiteSpace(field.GroupTitle))) + field.GroupTitle = $"-{field.FieldName}-"; + + // 按分组标题分组 + var groupFields = fields.GroupBy(field => field.GroupTitle).ToList(); + + // 按字段原始顺序处理分组 + var orderedGroups = new List>(); + + foreach (var field in fields) + { + var group = groupFields.First(g => g.Key == field.GroupTitle); + if (orderedGroups.Any(u => u.Key == group.Key)) continue; + + orderedGroups.Add(group); + } + + // 还原 GroupTitle 为空 + foreach (var field in fields.Where(field => field.GroupTitle == $"-{field.FieldName}-")) + field.GroupTitle = ""; + + return orderedGroups; + } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/ReportConfig/SysReportDataSourceService.cs b/Admin.NET/Admin.NET.Core/Service/ReportConfig/SysReportDataSourceService.cs new file mode 100644 index 00000000..e4d8238d --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/ReportConfig/SysReportDataSourceService.cs @@ -0,0 +1,181 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +using Furion.Localization; + +namespace Admin.NET.Core.Service; + +/// +/// 系统报表数据源服务 +/// +[ApiDescriptionSettings(Order = 500, Description = "报表数据源")] +public class SysReportDataSourceService : IDynamicApiController, ITransient +{ + private readonly SqlSugarRepository _reportDataSourceRep; + private readonly SqlSugarRepository _tenantRep; + private readonly ISqlSugarClient _db; + + public SysReportDataSourceService(SqlSugarRepository reportDataSourceRep, + SqlSugarRepository tenantRep, + ISqlSugarClient db + ) + { + _reportDataSourceRep = reportDataSourceRep; + _tenantRep = tenantRep; + _db = db; + } + + /// + /// 获取报表数据源分页列表 + /// + /// + /// + [DisplayName("获取报表数据源分页列表")] + public async Task> Page(PageReportDataSourceInput input) + { + var list = await _reportDataSourceRep.AsQueryable() + .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name.Trim())) + .Select(u => new SysReportDataSource(), true) + .OrderBuilder(input) + .ToPagedListAsync(input.Page, input.PageSize); + + // // 清空连接字符串 + // foreach (var item in list.Items) item.ConnectionString = ""; + + return list; + } + + /// + /// 增加报表数据源 + /// + /// + /// + [ApiDescriptionSettings(Name = "Add"), HttpPost] + [DisplayName("增加报表数据源")] + public async Task Add(AddReportDataSourceInput input) + { + var isExist = await _reportDataSourceRep.IsAnyAsync(u => u.Name == input.Name && u.Id != input.Id); + if (isExist) + throw Oops.Bah(ErrorCodeEnum.C1000); + + await _reportDataSourceRep.InsertAsync(input.Adapt()); + } + + /// + /// 更新报表数据源 + /// + /// + /// + [UnitOfWork] + [ApiDescriptionSettings(Name = "Update"), HttpPost] + [DisplayName("更新报表数据源")] + public async Task Update(UpdateReportDataSourceInput input) + { + var isExist = await _reportDataSourceRep.IsAnyAsync(u => u.Name == input.Name && u.Id != input.Id); + if (isExist) + throw Oops.Bah(ErrorCodeEnum.C1000); + + var updateEntity = input.Adapt(); + + // // 如果连接字符串为空,则使用原来的值 + // if (string.IsNullOrEmpty(updateEntity.ConnectionString)) + // { + // var entity = await _rep.GetFirstAsync(u => u.Id == input.Id); + // updateEntity.ConnectionString = entity.ConnectionString; + // } + + await _reportDataSourceRep.UpdateAsync(updateEntity); + } + + /// + /// 删除报表数据源 + /// + /// + /// + [UnitOfWork] + [ApiDescriptionSettings(Name = "Delete"), HttpPost] + [DisplayName("删除报表数据源")] + public async Task Delete(BaseIdInput input) + { + await _reportDataSourceRep.DeleteAsync(u => u.Id == input.Id); + } + + /// + /// 获取包含详细信息的数据源列表 + /// + /// + [NonAction] + public async Task> GetDataSourceListIncludeDetail() + { + var list = new List(); + + // 从配置获取数据源 + var configs = App.GetOptions().ConnectionConfigs; + foreach (var config in configs) + { + var configId = config.ConfigId.ToString(); + var db = _db.AsTenant().GetConnectionScope(configId); + list.Add(new SysReportDataSourceDetail + { + Id = configId, + Name = db.Ado.Connection.Database, + IsBuildIn = true, + DbType = config.DbType, + ConnectionString = db.Ado.Connection.ConnectionString, + }); + } + + // 从租户获取数据源 + var tenantList = await _tenantRep.AsQueryable() + .LeftJoin((u, o) => u.OrgId == o.Id).ClearFilter() + .Where((u, o) => u.TenantType == TenantTypeEnum.Db) + .Select((u, o) => new { u.Id, o.Name, u.DbType, u.Connection }) + .ToListAsync(); + foreach (var tenant in tenantList) + { + list.Add(new SysReportDataSourceDetail + { + Id = tenant.Id.ToString(), + Name = tenant.Name, + IsBuildIn = true, + DbType = tenant.DbType, + ConnectionString = tenant.Connection, + }); + } + + // 用户自定义 + var dsList = await _reportDataSourceRep.GetListAsync(); + foreach (var ds in dsList) + { + list.Add(new SysReportDataSourceDetail + { + Id = ds.Id.ToString(), + Name = ds.Name, + IsBuildIn = false, + DbType = Enum.Parse(ds.DbType), + ConnectionString = ds.ConnectionString, + }); + } + + foreach (var item in list.Where(item => item.IsBuildIn)) item.Name += L.Text["(内置)"]; + + return list; + } + + /// + /// 获取报表数据源列表 + /// + [DisplayName("获取报表数据源列表")] + public async Task> GetDataSourceList() + { + return (await GetDataSourceListIncludeDetail()).Select(u => new ReportDataSourceOutput + { + Id = u.Id, + Name = u.Name, + IsBuildIn = u.IsBuildIn + }).ToList(); + } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/ReportConfig/SysReportGroupService.cs b/Admin.NET/Admin.NET.Core/Service/ReportConfig/SysReportGroupService.cs new file mode 100644 index 00000000..b2e477b0 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/ReportConfig/SysReportGroupService.cs @@ -0,0 +1,77 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Service; + +/// +/// 系统报表分组服务 +/// +[ApiDescriptionSettings(Order = 500, Description = "报表分组")] +public class SysReportGroupService : IDynamicApiController, ITransient +{ + private readonly SqlSugarRepository _reportGroupRep; + + public SysReportGroupService(SqlSugarRepository reportGroupRep) + { + _reportGroupRep = reportGroupRep; + } + + /// + /// 获取报表分组列表 + /// + /// + [DisplayName("获取报表分组列表")] + public async Task> GetList() + { + return await _reportGroupRep.AsQueryable().OrderBy(u => u.Number).ToListAsync(); + } + + /// + /// 增加报表分组 + /// + /// + /// + [ApiDescriptionSettings(Name = "Add"), HttpPost] + [DisplayName("增加报表分组")] + public async Task Add(AddReportGroupInput input) + { + var isExist = await _reportGroupRep.IsAnyAsync(u => u.Number == input.Number && u.Id != input.Id); + if (isExist) + throw Oops.Bah(ErrorCodeEnum.C1003); + + await _reportGroupRep.InsertAsync(input.Adapt()); + } + + /// + /// 更新报表分组 + /// + /// + /// + [UnitOfWork] + [ApiDescriptionSettings(Name = "Update"), HttpPost] + [DisplayName("更新报表分组")] + public async Task Update(UpdateReportGroupInput input) + { + var isExist = await _reportGroupRep.IsAnyAsync(u => u.Number == input.Number && u.Id != input.Id); + if (isExist) + throw Oops.Bah(ErrorCodeEnum.C1003); + + await _reportGroupRep.UpdateAsync(input.Adapt()); + } + + /// + /// 删除报表分组 + /// + /// + /// + [UnitOfWork] + [ApiDescriptionSettings(Name = "Delete"), HttpPost] + [DisplayName("删除报表分组")] + public async Task Delete(BaseIdInput input) + { + await _reportGroupRep.DeleteAsync(u => u.Id == input.Id); + } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Role/SysRoleService.cs b/Admin.NET/Admin.NET.Core/Service/Role/SysRoleService.cs index 28f57fd8..c7ae7bc9 100644 --- a/Admin.NET/Admin.NET.Core/Service/Role/SysRoleService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Role/SysRoleService.cs @@ -80,7 +80,7 @@ public class SysRoleService : IDynamicApiController, ITransient public async Task> GetList() { // 当前用户已拥有的角色集合 - var roleIdList = _userManager.SuperAdmin ? new List() : await _sysUserRoleService.GetUserRoleIdList(_userManager.UserId); + var roleIdList = _userManager.SuperAdmin ? [] : await _sysUserRoleService.GetUserRoleIdList(_userManager.UserId); return await _sysRoleRep.AsQueryable() .WhereIF(!_userManager.SuperAdmin, u => u.TenantId == _userManager.TenantId) // 若非超管,则只能操作本租户的角色 @@ -106,7 +106,7 @@ public class SysRoleService : IDynamicApiController, ITransient // 授权角色基础菜单集合 var menuIdList = new List { - 1300000000111, 1300000000121, // 工作台 + 1300000000101, 1300000000111, 1300000000121, // 工作台 1310000000161, 1310000000162, 1310000000163, 1310000000164, 1310000000165, // 个人中心 }; await _sysRoleMenuService.GrantRoleMenu(new RoleMenuInput() { Id = roleId, MenuIdList = menuIdList }); @@ -138,9 +138,9 @@ public class SysRoleService : IDynamicApiController, ITransient [DisplayName("删除角色")] public async Task DeleteRole(DeleteRoleInput input) { - // 禁止删除系统管理员角色 + // 禁止删除系统内置角色 var sysRole = await _sysRoleRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002); - if (sysRole.Code == CommonConst.SysAdminRole) throw Oops.Oh(ErrorCodeEnum.D1019); + if(sysRole.SysFlag == YesNoEnum.Y) throw Oops.Oh(ErrorCodeEnum.D1019); // 若角色有用户则禁止删除 var userIds = await _sysUserRoleService.GetUserIdList(input.Id); diff --git a/Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs b/Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs index 583cd2a7..93637c7e 100644 --- a/Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs @@ -214,7 +214,8 @@ public class SysTenantService : IDynamicApiController, ITransient TenantId = tenantId, Name = tenantMark, Code = CommonConst.SysAdminRole, - DataScope = DataScopeEnum.All, + DataScope = DataScopeEnum.All, + SysFlag = YesNoEnum.Y, Remark = tenantMark }; await _sysRoleRep.InsertAsync(newRole); diff --git a/Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs b/Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs index 003f111d..ad43528a 100644 --- a/Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs +++ b/Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs @@ -105,13 +105,16 @@ public class SysUserService : IDynamicApiController, ITransient [ApiDescriptionSettings(Name = "Add"), HttpPost] [DisplayName("增加用户")] public virtual async Task AddUser(AddUserInput input) - { + { + // 是否有权操作此账号 + if (!_userManager.SuperAdmin && input.AccountType is AccountTypeEnum.SuperAdmin) throw Oops.Oh(ErrorCodeEnum.D1033); + var query = _sysUserRep.AsQueryable().ClearFilter(); if (await query.AnyAsync(u => u.Account == input.Account)) throw Oops.Oh(ErrorCodeEnum.D1003); if (!string.IsNullOrWhiteSpace(input.Phone) && await query.AnyAsync(u => u.Phone == input.Phone)) throw Oops.Oh(ErrorCodeEnum.D1032); - - var password = await _sysConfigService.GetConfigValueByCode(ConfigConst.SysPassword); - + + // 若没有设置密码则取默认密码 + var password = !string.IsNullOrWhiteSpace(input.Password) ? input.Password : await _sysConfigService.GetConfigValueByCode(ConfigConst.SysPassword); var user = input.Adapt(); user.Password = CryptogramHelper.Encrypt(password); var newUser = await _sysUserRep.AsInsertable(user).ExecuteReturnEntityAsync(); @@ -138,13 +141,22 @@ public class SysUserService : IDynamicApiController, ITransient [ApiDescriptionSettings(Name = "Update"), HttpPost] [DisplayName("更新用户")] public virtual async Task UpdateUser(UpdateUserInput input) - { + { var query = _sysUserRep.AsQueryable().ClearFilter().Where(u => u.Id != input.Id); if (await query.AnyAsync(u => u.Account == input.Account)) throw Oops.Oh(ErrorCodeEnum.D1003); - if (!string.IsNullOrWhiteSpace(input.Phone) && await query.AnyAsync(u => u.Phone == input.Phone)) throw Oops.Oh(ErrorCodeEnum.D1032); - - var user = input.Adapt(); - await _sysUserRep.AsUpdateable(user).IgnoreColumns(true).IgnoreColumns(u => new { u.Password, u.Status, u.TenantId }).ExecuteCommandAsync(); + if (!string.IsNullOrWhiteSpace(input.Phone) && await query.AnyAsync(u => u.Phone == input.Phone)) throw Oops.Oh(ErrorCodeEnum.D1032); + + // 若账号的角色和组织架构发生变化,则强制下线账号进行权限更新 + var user = await _sysUserRep.GetByIdAsync(input.Id); + var roleIds = await _sysUserRoleService.GetUserRoleIdList(input.Id); + if (input.OrgId != user.OrgId || !input.RoleIdList.OrderBy(u => u).SequenceEqual(roleIds.OrderBy(u => u))) + { + // 强制下线账号和失效Token + await OfflineAndExpireToken(user); + } + + // 更新用户 + await _sysUserRep.AsUpdateable(input.Adapt()).IgnoreColumns(true).IgnoreColumns(u => new { u.Password, u.Status, u.TenantId }).ExecuteCommandAsync(); // 更新用户附属机构 await UpdateRoleAndExtOrg(input); @@ -152,14 +164,6 @@ public class SysUserService : IDynamicApiController, ITransient // 删除用户机构缓存 SqlSugarFilter.DeleteUserOrgCache(input.Id, _sysUserRep.Context.CurrentConnectionConfig.ConfigId.ToString()); - // 若账号的角色和组织架构发生变化,则强制下线账号进行权限更新 - var roleIds = await _sysUserRoleService.GetUserRoleIdList(input.Id); - if (input.OrgId != user.OrgId || !input.RoleIdList.OrderBy(u => u).SequenceEqual(roleIds.OrderBy(u => u))) - { - // 强制下线账号和失效Token - await OfflineAndExpireToken(user); - } - // 更新域账号 await _sysUserLdapService.AddUserLdap(user.TenantId!.Value, user.Id, user.Account, input.DomainAccount); diff --git a/Admin.NET/Admin.NET.Core/Service/User/UserManager.cs b/Admin.NET/Admin.NET.Core/Service/User/UserManager.cs index 24f06f18..17df17d8 100644 --- a/Admin.NET/Admin.NET.Core/Service/User/UserManager.cs +++ b/Admin.NET/Admin.NET.Core/Service/User/UserManager.cs @@ -43,6 +43,11 @@ public class UserManager : IScoped /// public string NickName => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.NickName)?.Value; + /// + /// 账号类型 + /// + public AccountTypeEnum? AccountType => int.TryParse(_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.AccountType)?.Value, out var val) ? (AccountTypeEnum?)val : null; + /// /// 是否超级管理员 /// diff --git a/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs b/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs index 3115758a..81ed8a4d 100644 --- a/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs @@ -1,735 +1,735 @@ -// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 -// -// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 -// -// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! - -namespace Admin.NET.Core.Service; - -/// -/// 微信支付服务 🧩 -/// -[ApiDescriptionSettings(Order = 210, Description = "微信支付")] -public class SysWechatPayService : IDynamicApiController, ITransient -{ - private static readonly List wechatPayEventHandlers = []; - - /// - /// 注册支付记录变化事件处理器 - /// - /// 处理器 - /// 排序,数据越大越先执行 - public static void AddPayEventInterceptor(WechatPayEventInterceptor eh, int order) - { - eh.Order = order; - wechatPayEventHandlers.Add(eh); - wechatPayEventHandlers.Sort((a, b) => b.Order - a.Order); - } - - private readonly SqlSugarRepository _sysWechatPayRep; - private readonly SqlSugarRepository _sysWechatRefundRep; - private readonly WechatPayOptions _wechatPayOptions; - private readonly PayCallBackOptions _payCallBackOptions; - - private readonly WechatTenpayClient _wechatTenpayClient; - - public SysWechatPayService(SqlSugarRepository sysWechatPayRep, - SqlSugarRepository sysWechatRefundRep, - IOptions wechatPayOptions, - IOptions payCallBackOptions) - { - _sysWechatPayRep = sysWechatPayRep; - _sysWechatRefundRep = sysWechatRefundRep; - _wechatPayOptions = wechatPayOptions.Value; - _payCallBackOptions = payCallBackOptions.Value; - - _wechatTenpayClient = CreateTenpayClient(); - } - - /// - /// 初始化微信支付客户端 - /// - /// - private WechatTenpayClient CreateTenpayClient() - { - var cerFilePath = Path.Combine(App.WebHostEnvironment.ContentRootPath, _wechatPayOptions.MerchantCertificatePrivateKey.Replace("/", Path.DirectorySeparatorChar.ToString())); - - if (!File.Exists(cerFilePath)) - Log.Warning("商户证书文件不存在:" + cerFilePath); - - var tenpayClientOptions = new WechatTenpayClientOptions() - { - MerchantId = _wechatPayOptions.MerchantId, - MerchantV3Secret = _wechatPayOptions.MerchantV3Secret, - MerchantCertificateSerialNumber = _wechatPayOptions.MerchantCertificateSerialNumber, - MerchantCertificatePrivateKey = File.Exists(cerFilePath) ? File.ReadAllText(cerFilePath) : "", - PlatformCertificateManager = new InMemoryCertificateManager() - }; - return new WechatTenpayClient(tenpayClientOptions); - } - - /// - /// 生成JSAPI调起支付所需参数 🔖 - /// - /// - /// - [DisplayName("生成JSAPI调起支付所需参数")] - public WechatPayParaOutput GenerateParametersForJsapiPay(WechatPayParaInput input) - { - var result = _wechatTenpayClient.GenerateParametersForJsapiPayRequest(_wechatPayOptions.AppId, input.PrepayId); - return result.Adapt(); - } - - /// - /// 微信支付统一下单获取Id(商户直连) 🔖 - /// - [DisplayName("微信支付统一下单获取Id(商户直连)")] - public async Task CreatePayTransaction([FromBody] WechatPayTransactionInput input) - { - string outTradeNumber = DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000); // 微信需要的订单号(唯一) - - // 检查订单信息是否已存在(使用“商户交易单号+状态”唯一性判断) - SysWechatPay wechatPay = null; - if (!string.IsNullOrEmpty(input.OrderId)) - { - wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OrderId == input.OrderId && u.OrderStatus == input.OrderStatus); - if (wechatPay != null) - { - outTradeNumber = wechatPay.OutTradeNumber; - } - } - - var request = new CreatePayTransactionJsapiRequest() - { - OutTradeNumber = outTradeNumber, - AppId = _wechatPayOptions.AppId, - Description = input.Description, - Attachment = input.Attachment, - GoodsTag = input.GoodsTag, - ExpireTime = DateTimeOffset.Now.AddMinutes(10), - NotifyUrl = _payCallBackOptions.WechatPayUrl, - Amount = new CreatePayTransactionJsapiRequest.Types.Amount() { Total = input.Total }, - Payer = new CreatePayTransactionJsapiRequest.Types.Payer() { OpenId = input.OpenId } - }; - var response = await _wechatTenpayClient.ExecuteCreatePayTransactionJsapiAsync(request); - if (!response.IsSuccessful()) - throw Oops.Oh(response.ErrorMessage); - - if (wechatPay == null) - { - // 保存订单信息 - wechatPay = new SysWechatPay() - { - AppId = _wechatPayOptions.AppId, - MerchantId = _wechatPayOptions.MerchantId, - OutTradeNumber = request.OutTradeNumber, - Description = input.Description, - Attachment = input.Attachment, - GoodsTag = input.GoodsTag, - Total = input.Total, - OpenId = input.OpenId, - TransactionId = "", - OrderId = input.OrderId, - OrderStatus = input.OrderStatus, - Tags = input.Tags, - BusinessId = input.BusinessId, - }; - await _sysWechatPayRep.InsertAsync(wechatPay); - } - - var singInfo = GenerateParametersForJsapiPay(new WechatPayParaInput() { PrepayId = response.PrepayId }); - return new CreatePayTransactionOutput - { - PrepayId = response.PrepayId, - OutTradeNumber = request.OutTradeNumber, - SingInfo = singInfo - }; - } - - /// - /// 微信支付统一下单(商户直连)Native 🔖 - /// - [DisplayName("微信支付统一下单(商户直连)Native")] - public async Task CreatePayTransactionNative([FromBody] WechatPayTransactionInput input) - { - var request = new CreatePayTransactionNativeRequest() - { - OutTradeNumber = DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000), // 微信需要的订单号(唯一) - AppId = _wechatPayOptions.AppId, - Description = input.Description, - Attachment = input.Attachment, - GoodsTag = input.GoodsTag, - ExpireTime = DateTimeOffset.Now.AddMinutes(10), - NotifyUrl = _payCallBackOptions.WechatPayUrl, - Amount = new CreatePayTransactionNativeRequest.Types.Amount() { Total = input.Total }, - //Payer = new CreatePayTransactionNativeRequest.Types.Payer() { OpenId = input.OpenId } - Scene = new CreatePayTransactionNativeRequest.Types.Scene() { ClientIp = "127.0.0.1" } - }; - var response = await _wechatTenpayClient.ExecuteCreatePayTransactionNativeAsync(request); - if (!response.IsSuccessful()) - { - JSON.Serialize(response).LogInformation(); - throw Oops.Oh(response.ErrorMessage); - } - // 保存订单信息 - var wechatPay = new SysWechatPay() - { - AppId = _wechatPayOptions.AppId, - MerchantId = _wechatPayOptions.MerchantId, - OutTradeNumber = request.OutTradeNumber, - Description = input.Description, - Attachment = input.Attachment, - GoodsTag = input.GoodsTag, - Total = input.Total, - OpenId = input.OpenId, - TransactionId = "", - QrcodeContent = response.QrcodeUrl, - Tags = input.Tags, - BusinessId = input.BusinessId, - }; - await _sysWechatPayRep.InsertAsync(wechatPay); - return new CreatePayTransactionNativeOutput - { - OutTradeNumber = request.OutTradeNumber, - QrcodeUrl = response.QrcodeUrl - }; - } - - /// - /// 微信支付统一下单获取Id(服务商模式) 🔖 - /// - [DisplayName("微信支付统一下单获取Id(服务商模式)")] - public async Task CreatePayPartnerTransaction([FromBody] WechatPayTransactionInput input) - { - string outTradeNumber = DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000); // 微信需要的订单号(唯一) - - // 检查订单信息是否已存在(使用“商户交易单号+状态”唯一性判断) - var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OrderId == input.OrderId && u.OrderStatus == input.OrderStatus); - if (wechatPay != null) - { - outTradeNumber = wechatPay.OutTradeNumber; - } - - var request = new CreatePayPartnerTransactionJsapiRequest() - { - OutTradeNumber = outTradeNumber, - AppId = _wechatPayOptions.AppId, - MerchantId = _wechatPayOptions.MerchantId, - SubAppId = _wechatPayOptions.AppId, - SubMerchantId = _wechatPayOptions.MerchantId, - Description = input.Description, - Attachment = input.Attachment, - GoodsTag = input.GoodsTag, - ExpireTime = DateTimeOffset.Now.AddMinutes(10), - NotifyUrl = _payCallBackOptions.WechatPayUrl, - Amount = new CreatePayPartnerTransactionJsapiRequest.Types.Amount() { Total = input.Total }, - Payer = new CreatePayPartnerTransactionJsapiRequest.Types.Payer() { OpenId = input.OpenId } - }; - var response = await _wechatTenpayClient.ExecuteCreatePayPartnerTransactionJsapiAsync(request); - if (!response.IsSuccessful()) - throw Oops.Oh($"JSAPI 下单失败(状态码:{response.GetRawStatus()},错误代码:{response.ErrorCode},错误描述:{response.ErrorMessage})"); - if (wechatPay == null) - { - // 保存订单信息 - wechatPay = new SysWechatPay() - { - AppId = _wechatPayOptions.AppId, - MerchantId = _wechatPayOptions.MerchantId, - SubAppId = _wechatPayOptions.AppId, - SubMerchantId = _wechatPayOptions.MerchantId, - OutTradeNumber = request.OutTradeNumber, - Description = input.Description, - Attachment = input.Attachment, - GoodsTag = input.GoodsTag, - Total = input.Total, - OpenId = input.OpenId, - TransactionId = "" - }; - await _sysWechatPayRep.InsertAsync(wechatPay); - } - - return new CreatePayTransactionOutput - { - PrepayId = response.PrepayId, - OutTradeNumber = request.OutTradeNumber - }; - } - - /// - /// 获取支付订单详情 🔖 - /// - /// - /// - [DisplayName("获取支付订单详情")] - public async Task GetPayInfo(string tradeId) - { - return await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == tradeId); - } - - /// - /// 获取支付订单详情(微信接口) 🔖 - /// - /// - /// - [DisplayName("获取支付订单详情(微信接口)")] - public async Task GetPayInfoFromWechat(string tradeId) - { - var request = new GetPayTransactionByOutTradeNumberRequest(); - request.OutTradeNumber = tradeId; - var response = await _wechatTenpayClient.ExecuteGetPayTransactionByOutTradeNumberAsync(request); - // 修改订单支付状态 - var wechatPayOld = await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == response.OutTradeNumber - && u.MerchantId == response.MerchantId); - SysWechatPay wechatPayNew = null; - if (wechatPayOld != null) - wechatPayNew = wechatPayOld.DeepCopy(); - // 如果状态不一致就更新数据库中的记录 - if (wechatPayNew != null && wechatPayNew.TradeState != response.TradeState) - { - wechatPayNew.OpenId = response.Payer?.OpenId; - wechatPayNew.TransactionId = response.TransactionId; // 支付订单号 - wechatPayNew.TradeType = response.TradeType; // 交易类型 - wechatPayNew.TradeState = response.TradeState; // 交易状态 - wechatPayNew.TradeStateDescription = response.TradeStateDescription; // 交易状态描述 - wechatPayNew.BankType = response.BankType; // 付款银行类型 - if (response.Amount != null) - { - wechatPayNew.Total = response.Amount.Total; // 订单总金额 - wechatPayNew.PayerTotal = response.Amount.PayerTotal; // 用户支付金额 - } - if (response.SuccessTime.HasValue) - wechatPayNew.SuccessTime = response.SuccessTime.Value.DateTime; // 支付完成时间 - else - wechatPayNew.SuccessTime = DateTime.Now; - await _sysWechatPayRep.AsUpdateable(wechatPayNew).IgnoreColumns(true).ExecuteCommandAsync(); - } - if (wechatPayOld == null || wechatPayOld.TradeState != wechatPayNew.TradeState) - { - // 没必要等所有回调事件处理完再返回给微信,开一个Task执行 - _ = Task.Run(async () => - { - foreach (var eh in wechatPayEventHandlers) - { - try - { - //这里一定要用 DeepCopy 来创一个新的对象传进不,不然会被外面的 主线程改变就麻烦了 - if (!await eh.PayInforChanged(wechatPayOld, wechatPayNew.DeepCopy())) - break; - } - catch (Exception ex) - { - $"GetPayInfoFromWechat 中执行微信支付回调{eh.GetType().Name}出错".LogError(ex); - } - } - }); - } - // 下面这里创建一个新的对象,是因为不想把全部字段都返回 - var result = new SysWechatPay() - { - AppId = _wechatPayOptions.AppId, - MerchantId = _wechatPayOptions.MerchantId, - SubAppId = _wechatPayOptions.AppId, - SubMerchantId = _wechatPayOptions.MerchantId, - OutTradeNumber = request.OutTradeNumber, - Attachment = response.Attachment, - TransactionId = response.TransactionId, - TradeType = response.TradeType, // 交易类型 - TradeState = response.TradeState, // 交易状态 - TradeStateDescription = response.TradeStateDescription, // 交易状态描述 - BankType = response.BankType, // 付款银行类型 - SuccessTime = response.SuccessTime.HasValue ? response.SuccessTime.Value.DateTime : DateTime.Now // 支付完成时间 - }; - - return result; - } - - /// - /// 微信支付成功回调(商户直连) 🔖 - /// - /// - [AllowAnonymous] - [DisplayName("微信支付成功回调(商户直连)")] - public async Task PayCallBack() - { - using var ms = new MemoryStream(); - await App.HttpContext.Request.Body.CopyToAsync(ms); - var b = ms.ToArray(); - var callbackJson = Encoding.UTF8.GetString(b); - - var callbackModel = _wechatTenpayClient.DeserializeEvent(callbackJson); - if ("TRANSACTION.SUCCESS".Equals(callbackModel.EventType)) - { - var callbackResource = _wechatTenpayClient.DecryptEventResource(callbackModel); - - // 修改订单支付状态 - var wechatPayOld = await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == callbackResource.OutTradeNumber - && u.MerchantId == callbackResource.MerchantId); - if (wechatPayOld == null) return null; - var wechatPayNew = wechatPayOld.DeepCopy(); - if (callbackResource.Payer != null) - wechatPayNew.OpenId = callbackResource.Payer.OpenId; // 支付者标识 - wechatPayNew.TransactionId = callbackResource.TransactionId; // 支付订单号 - wechatPayNew.TradeType = callbackResource.TradeType; // 交易类型 - wechatPayNew.TradeState = callbackResource.TradeState; // 交易状态 - wechatPayNew.TradeStateDescription = callbackResource.TradeStateDescription; // 交易状态描述 - wechatPayNew.BankType = callbackResource.BankType; // 付款银行类型 - wechatPayNew.Total = callbackResource.Amount.Total; // 订单总金额 - wechatPayNew.PayerTotal = callbackResource.Amount.PayerTotal; // 用户支付金额 - wechatPayNew.SuccessTime = callbackResource.SuccessTime.DateTime; // 支付完成时间 - - await _sysWechatPayRep.AsUpdateable(wechatPayNew).IgnoreColumns(true).ExecuteCommandAsync(); - // 因为这个是回调给微信的,所以这里没必要等所有回调事件处理完再返回给微信,开一个Task执行 - if (wechatPayOld.TradeState != wechatPayNew.TradeState) - { - _ = Task.Run(async () => - { - foreach (var eh in wechatPayEventHandlers) - { - try - { - if (!await eh.PayInforChanged(wechatPayOld, wechatPayNew)) - break; - } - catch (Exception ex) - { - $"PayCallBack 中执行微信支付回调{eh.GetType().Name}出错".LogError(ex); - } - } - }); - } - return new WechatPayOutput() - { - Total = wechatPayNew.Total, - Attachment = wechatPayNew.Attachment, - GoodsTag = wechatPayNew.GoodsTag, - OrderId = long.Parse(wechatPayNew.OrderId) - }; - } - - return null; - } - - /// - /// 微信退款回调(商户直连) 🔖 - /// - /// - [AllowAnonymous] - [DisplayName("微信退款回调(商户直连)")] - public async Task RefundCallBack() - { - using var ms = new MemoryStream(); - await App.HttpContext.Request.Body.CopyToAsync(ms); - var b = ms.ToArray(); - var callbackJson = Encoding.UTF8.GetString(b); - - var callbackModel = _wechatTenpayClient.DeserializeEvent(callbackJson); - if ("REFUND.SUCCESS".Equals(callbackModel.EventType)) - { - // 参考:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/refund-result-notice.html - try - { - var callbackRefundResource = _wechatTenpayClient.DecryptEventResource(callbackModel); - // 修改订单支付状态 - var wechatRefund = await _sysWechatRefundRep.GetFirstAsync(u => u.OutRefundNumber == callbackRefundResource.OutRefundNumber); - if (wechatRefund == null) return null; - wechatRefund.RefundStatus = callbackRefundResource.RefundStatus; // 交易状态 - wechatRefund.SuccessTime = callbackRefundResource.SuccessTime.Value.DateTime; // 支付完成时间 - - await _sysWechatRefundRep.AsUpdateable(wechatRefund).IgnoreColumns(true).ExecuteCommandAsync(); - // 有退款,刷新一下订单状态(通过主动查询Wechat接口获取) - // 通过 GetPayInfoFromWechat 也会触发 WechatPayEventHandler,所以这个回调中不用主动调用 - await GetPayInfoFromWechat(callbackRefundResource.OutTradeNumber); - } - catch (Exception ex) - { - "微信退款回调时出错:".LogError(ex); - } - } - else - { - callbackModel.EventType.LogInformation(); - } - - return null; - } - - /// - /// 微信支付成功回调(服务商模式) 🔖 - /// - /// - [AllowAnonymous] - [DisplayName("微信支付成功回调(服务商模式)")] - public async Task PayPartnerCallBack() - { - using var ms = new MemoryStream(); - await App.HttpContext.Request.Body.CopyToAsync(ms); - var b = ms.ToArray(); - var callbackJson = Encoding.UTF8.GetString(b); - - var callbackModel = _wechatTenpayClient.DeserializeEvent(callbackJson); - if ("TRANSACTION.SUCCESS".Equals(callbackModel.EventType)) - { - var callbackResource = _wechatTenpayClient.DecryptEventResource(callbackModel); - - // 修改订单支付状态 - var wechatPayOld = await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == callbackResource.OutTradeNumber - && u.MerchantId == callbackResource.MerchantId); - - if (wechatPayOld == null) return; - var wechatPayNew = wechatPayOld.DeepCopy(); - //wechatPay.OpenId = callbackResource.Payer.OpenId; // 支付者标识 - //wechatPay.MerchantId = callbackResource.MerchantId; // 微信商户号 - //wechatPay.OutTradeNumber = callbackResource.OutTradeNumber; // 商户订单号 - wechatPayNew.TransactionId = callbackResource.TransactionId; // 支付订单号 - wechatPayNew.TradeType = callbackResource.TradeType; // 交易类型 - wechatPayNew.TradeState = callbackResource.TradeState; // 交易状态 - wechatPayNew.TradeStateDescription = callbackResource.TradeStateDescription; // 交易状态描述 - wechatPayNew.BankType = callbackResource.BankType; // 付款银行类型 - wechatPayNew.Total = callbackResource.Amount.Total; // 订单总金额 - wechatPayNew.PayerTotal = callbackResource.Amount.PayerTotal; // 用户支付金额 - wechatPayNew.SuccessTime = callbackResource.SuccessTime.DateTime; // 支付完成时间 - - await _sysWechatPayRep.AsUpdateable(wechatPayNew).IgnoreColumns(true).ExecuteCommandAsync(); - // 因为这个是回调给微信的,所以这里没必要等所有回调事件处理完再返回给微信,开一个Task执行 - if (wechatPayOld.TradeState != wechatPayNew.TradeState) - { - _ = Task.Run(async () => - { - foreach (var eh in wechatPayEventHandlers) - { - try - { - if (!await eh.PayInforChanged(wechatPayOld, wechatPayNew)) - break; - } - catch (Exception ex) - { - $"PayPartnerCallBack 中执行微信支付回调{eh.GetType().Name}出错".LogError(ex); - } - } - }); - } - } - } - - /// - /// 退款申请 🔖 - /// https://pay.weixin.qq.com/docs/merchant/apis/mini-program-payment/create.html - /// - /// - /// - [DisplayName("微信退款申请)")] - public async Task Refund(RefundRequestInput input) - { - var vechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == input.OutTradeNumber); - if (vechatPay == null) - throw Oops.Bah("没有相应支付记录"); - - var request = new CreateRefundDomesticRefundRequest() - { - OutTradeNumber = input.OutTradeNumber, - OutRefundNumber = "REFUND_" + DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff"), - NotifyUrl = _payCallBackOptions.WechatRefundUrl, - Amount = new CreateRefundDomesticRefundRequest.Types.Amount() - { - Total = input.Total, - Refund = input.Refund - }, - Reason = input.Reason, - }; - var response = await _wechatTenpayClient.ExecuteCreateRefundDomesticRefundAsync(request); - - if (!response.IsSuccessful()) - { - // 退款失败,该单可能已经退款了,所以主动查询微信接口更新状态 - try - { - await this.GetPayInfoFromWechat(input.OutTradeNumber); - } - catch { } - throw Oops.Oh($"JSAPI 退款申请失败(状态码:{response.GetRawStatus()},错误代码:{response.ErrorCode},错误描述:{response.ErrorMessage})"); - } - - var wechatRefund = await _sysWechatRefundRep.GetFirstAsync(u => u.OutTradeNumber == input.OutTradeNumber); - if (wechatRefund == null) - { - // 保存退款申请信息 - wechatRefund = new SysWechatRefund() - { - TransactionId = vechatPay.TransactionId, - OutTradeNumber = input.OutTradeNumber, - OutRefundNumber = request.OutRefundNumber, // 每笔付款只退一次,所以这里直接用付款单号 - Reason = request.Reason, - Refund = input.Refund, - RefundId = response.RefundId, - Total = input.Total, - NotifyUrl = _payCallBackOptions.WechatRefundUrl, - OrderId = input.OrderId, - RefundStatus = input.OrderStatus, - MerchantGoodsId = input.MerchantGoodsId, - GoodsName = input.GoodsName, - UnitPrice = input.UnitPrice, - RefundAmount = input.RefundAmount, - RefundQuantity = input.RefundQuantity, - Attachment = input.Attachment, - Remark = input.Remark - }; - await _sysWechatRefundRep.InsertAsync(wechatRefund); - // 发送了退款请求也要更新原定单的状态(从微信查询) - await this.GetPayInfoFromWechat(input.OutTradeNumber); - } - } - - /// - /// 查询单笔退款(通过商户退款单号) 🔖 - /// https://pay.weixin.qq.com/docs/merchant/apis/mini-program-payment/query-by-out-refund-no.html - /// - /// - /// - [DisplayName("微信查询单笔退款)")] - public async Task GetRefundByOutRefundNumber(string outRefundNumber) - { - var request = new GetRefundDomesticRefundByOutRefundNumberRequest() - { - OutRefundNumber = outRefundNumber - }; - return await _wechatTenpayClient.ExecuteGetRefundDomesticRefundByOutRefundNumberAsync(request); - } - - /// - /// 微信支付订单号查询(校正) 🔖 - /// https://api.mch.weixin.qq.com/v3/pay/transactions/id/{transaction_id} - /// - /// - /// - [DisplayName("微信支付订单号查询(校正)")] - public async Task GetPayTransactionByIdAsync(string transactionId) - { - if (string.IsNullOrEmpty(transactionId)) - throw Oops.Oh("TransactionId 不能为空"); - - if (string.IsNullOrEmpty(_wechatPayOptions.MerchantId) || string.IsNullOrEmpty(_wechatPayOptions.MerchantCertificateSerialNumber)) - throw Oops.Oh("商户号或证书序列号不能为空,请检查支付配置"); - - var request = new GetPayTransactionByIdRequest() - { - MerchantId = _wechatPayOptions.MerchantId, - TransactionId = transactionId, - WechatpaySerialNumber = _wechatPayOptions.MerchantCertificateSerialNumber - }; - var response = await _wechatTenpayClient.ExecuteGetPayTransactionByIdAsync(request); - if (response.TradeState == "SUCCESS" || response.TradeState == "CLOSED" || response.TradeState == "NOTPAY") - { - // 修正订单支付状态 - var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.TransactionId == request.TransactionId && u.MerchantId == request.MerchantId); - if (wechatPay != null && string.IsNullOrEmpty(wechatPay.TradeState)) - { - wechatPay.TradeType = response.TradeType; // 交易类型 - wechatPay.TradeState = response.TradeState; // 交易状态 - wechatPay.TradeStateDescription = response.TradeStateDescription; // 交易状态描述 - wechatPay.OpenId = response.Payer?.OpenId;// 付款用户OpenId - wechatPay.BankType = response.BankType; // 付款银行类型 - wechatPay.PayerTotal = response.Amount?.PayerTotal; // 用户支付金额 - wechatPay.SuccessTime = response.SuccessTime?.DateTime; // 支付完成时间 - await _sysWechatPayRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync(); - return wechatPay.Adapt(); - } - } - return response.Adapt(); - } - - /// - /// 商户订单号查询(校正) 🔖 - /// https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no} - /// - /// - /// - [DisplayName("微信商户订单号查询(校正)")] - public async Task GetPayTransactionByOutTradeNumberAsync(string outTradeNumber) - { - if (string.IsNullOrEmpty(outTradeNumber)) - throw Oops.Oh("商户订单号(OutTradeNumber)不能为空"); - - if (string.IsNullOrEmpty(_wechatPayOptions.MerchantId) || string.IsNullOrEmpty(_wechatPayOptions.MerchantCertificateSerialNumber)) - throw Oops.Oh("商户号或证书序列号不能为空,请检查支付配置"); - - var request = new GetPayTransactionByOutTradeNumberRequest() - { - MerchantId = _wechatPayOptions.MerchantId, - OutTradeNumber = outTradeNumber, - WechatpaySerialNumber = _wechatPayOptions.MerchantCertificateSerialNumber, - }; - var response = await _wechatTenpayClient.ExecuteGetPayTransactionByOutTradeNumberAsync(request); - if (response.TradeState == "SUCCESS" || response.TradeState == "CLOSED" || response.TradeState == "NOTPAY") - { - // 修正订单支付状态 - var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == outTradeNumber && u.MerchantId == request.MerchantId); - if (wechatPay != null && string.IsNullOrEmpty(wechatPay.TradeState)) - { - wechatPay.TransactionId = response.TransactionId; // 支付订单号 - wechatPay.TradeType = response.TradeType; // 交易类型 - wechatPay.TradeState = response.TradeState; // 交易状态 - wechatPay.TradeStateDescription = response.TradeStateDescription; // 交易状态描述 - wechatPay.OpenId = response.Payer?.OpenId;// 付款用户OpenId - wechatPay.BankType = response.BankType; // 付款银行类型 - wechatPay.PayerTotal = response.Amount?.PayerTotal; // 用户支付金额 - wechatPay.SuccessTime = response.SuccessTime?.DateTime; // 支付完成时间 - await _sysWechatPayRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync(); - return wechatPay.Adapt(); - } - } - return response.Adapt(); - } - - /// - /// 获取支付记录分页列表 🔖 - /// - /// PageSysWechatPayInput - /// - [DisplayName("获取支付记录分页列表")] - public async Task> PageAsync(PageSysWechatPayInput input) - { - var query = _sysWechatPayRep.AsQueryable() - .WhereIF(!string.IsNullOrWhiteSpace(input.OrderId), u => u.OrderId == input.OrderId) - .WhereIF(!string.IsNullOrWhiteSpace(input.OrderStatus), u => u.OrderStatus == input.OrderStatus) - .WhereIF(!string.IsNullOrWhiteSpace(input.OutTradeNumber), u => u.OutTradeNumber.Contains(input.OutTradeNumber.Trim())); - - if (input.SuccessTimeRange != null && input.SuccessTimeRange.Count > 0) - { - DateTime? start = input.SuccessTimeRange[0]; - query.WhereIF(start.HasValue, u => u.SuccessTime > start); - if (input.SuccessTimeRange.Count > 1 && input.SuccessTimeRange[1].HasValue) - { - var end = input.SuccessTimeRange[1].Value.AddDays(1); - query.Where(u => u.SuccessTime < end); - } - } - if (input.ExpireTimeRange != null && input.ExpireTimeRange.Count > 0) - { - DateTime? start = input.ExpireTimeRange[0]; - query.WhereIF(start.HasValue, u => u.ExpireTime > start); - if (input.ExpireTimeRange.Count > 1 && input.ExpireTimeRange[1].HasValue) - { - var end = input.ExpireTimeRange[1].Value.AddDays(1); - query.Where(u => u.ExpireTime < end); - } - } - query.OrderByDescending(u => u.CreateTime); - return await query.ToPagedListAsync(input.Page, input.PageSize); - } - - /// - /// 根据支付Id获取退款信息列表 🔖 - /// - /// - /// - /// - [DisplayName("根据支付Id获取退款信息列表")] - public async Task> GetRefundList([FromQuery] string transactionId, [FromQuery] string outTradeNumber) - { - return await _sysWechatRefundRep.AsQueryable() - .WhereIF(!string.IsNullOrEmpty(transactionId), u => u.TransactionId == transactionId) - .WhereIF(!string.IsNullOrEmpty(outTradeNumber), u => u.OutTradeNumber == outTradeNumber) - .ToListAsync(); - } +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core.Service; + +/// +/// 微信支付服务 🧩 +/// +[ApiDescriptionSettings(Order = 210, Description = "微信支付")] +public class SysWechatPayService : IDynamicApiController, ITransient +{ + private static readonly List wechatPayEventHandlers = []; + + /// + /// 注册支付记录变化事件处理器 + /// + /// 处理器 + /// 排序,数据越大越先执行 + public static void AddPayEventInterceptor(WechatPayEventInterceptor eh, int order) + { + eh.Order = order; + wechatPayEventHandlers.Add(eh); + wechatPayEventHandlers.Sort((a, b) => b.Order - a.Order); + } + + private readonly SqlSugarRepository _sysWechatPayRep; + private readonly SqlSugarRepository _sysWechatRefundRep; + private readonly WechatPayOptions _wechatPayOptions; + private readonly PayCallBackOptions _payCallBackOptions; + + private readonly WechatTenpayClient _wechatTenpayClient; + + public SysWechatPayService(SqlSugarRepository sysWechatPayRep, + SqlSugarRepository sysWechatRefundRep, + IOptions wechatPayOptions, + IOptions payCallBackOptions) + { + _sysWechatPayRep = sysWechatPayRep; + _sysWechatRefundRep = sysWechatRefundRep; + _wechatPayOptions = wechatPayOptions.Value; + _payCallBackOptions = payCallBackOptions.Value; + + _wechatTenpayClient = CreateTenpayClient(); + } + + /// + /// 初始化微信支付客户端 + /// + /// + private WechatTenpayClient CreateTenpayClient() + { + var cerFilePath = Path.Combine(App.WebHostEnvironment.ContentRootPath, _wechatPayOptions.MerchantCertificatePrivateKey.Replace("/", Path.DirectorySeparatorChar.ToString())); + + if (!File.Exists(cerFilePath)) + Log.Warning("商户证书文件不存在:" + cerFilePath); + + var tenpayClientOptions = new WechatTenpayClientOptions() + { + MerchantId = _wechatPayOptions.MerchantId, + MerchantV3Secret = _wechatPayOptions.MerchantV3Secret, + MerchantCertificateSerialNumber = _wechatPayOptions.MerchantCertificateSerialNumber, + MerchantCertificatePrivateKey = File.Exists(cerFilePath) ? File.ReadAllText(cerFilePath) : "", + PlatformCertificateManager = new InMemoryCertificateManager() + }; + return new WechatTenpayClient(tenpayClientOptions); + } + + /// + /// 生成JSAPI调起支付所需参数 🔖 + /// + /// + /// + [DisplayName("生成JSAPI调起支付所需参数")] + public WechatPayParaOutput GenerateParametersForJsapiPay(WechatPayParaInput input) + { + var result = _wechatTenpayClient.GenerateParametersForJsapiPayRequest(_wechatPayOptions.AppId, input.PrepayId); + return result.Adapt(); + } + + /// + /// 微信支付统一下单获取Id(商户直连) 🔖 + /// + [DisplayName("微信支付统一下单获取Id(商户直连)")] + public async Task CreatePayTransaction([FromBody] WechatPayTransactionInput input) + { + string outTradeNumber = DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000); // 微信需要的订单号(唯一) + + // 检查订单信息是否已存在(使用“商户交易单号+状态”唯一性判断) + SysWechatPay wechatPay = null; + if (!string.IsNullOrEmpty(input.OrderId)) + { + wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OrderId == input.OrderId && u.OrderStatus == input.OrderStatus && input.Total == u.Total); + if (wechatPay != null) + { + outTradeNumber = wechatPay.OutTradeNumber; + } + } + + var request = new CreatePayTransactionJsapiRequest() + { + OutTradeNumber = outTradeNumber, + AppId = _wechatPayOptions.AppId, + Description = input.Description, + Attachment = input.Attachment, + GoodsTag = input.GoodsTag, + ExpireTime = DateTimeOffset.Now.AddMinutes(10), + NotifyUrl = _payCallBackOptions.WechatPayUrl, + Amount = new CreatePayTransactionJsapiRequest.Types.Amount() { Total = input.Total }, + Payer = new CreatePayTransactionJsapiRequest.Types.Payer() { OpenId = input.OpenId } + }; + var response = await _wechatTenpayClient.ExecuteCreatePayTransactionJsapiAsync(request); + if (!response.IsSuccessful()) + throw Oops.Oh(response.ErrorMessage); + + if (wechatPay == null) + { + // 保存订单信息 + wechatPay = new SysWechatPay() + { + AppId = _wechatPayOptions.AppId, + MerchantId = _wechatPayOptions.MerchantId, + OutTradeNumber = request.OutTradeNumber, + Description = input.Description, + Attachment = input.Attachment, + GoodsTag = input.GoodsTag, + Total = input.Total, + OpenId = input.OpenId, + TransactionId = "", + OrderId = input.OrderId, + OrderStatus = input.OrderStatus, + Tags = input.Tags, + BusinessId = input.BusinessId, + }; + await _sysWechatPayRep.InsertAsync(wechatPay); + } + + var singInfo = GenerateParametersForJsapiPay(new WechatPayParaInput() { PrepayId = response.PrepayId }); + return new CreatePayTransactionOutput + { + PrepayId = response.PrepayId, + OutTradeNumber = request.OutTradeNumber, + SingInfo = singInfo + }; + } + + /// + /// 微信支付统一下单(商户直连)Native 🔖 + /// + [DisplayName("微信支付统一下单(商户直连)Native")] + public async Task CreatePayTransactionNative([FromBody] WechatPayTransactionInput input) + { + var request = new CreatePayTransactionNativeRequest() + { + OutTradeNumber = DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000), // 微信需要的订单号(唯一) + AppId = _wechatPayOptions.AppId, + Description = input.Description, + Attachment = input.Attachment, + GoodsTag = input.GoodsTag, + ExpireTime = DateTimeOffset.Now.AddMinutes(10), + NotifyUrl = _payCallBackOptions.WechatPayUrl, + Amount = new CreatePayTransactionNativeRequest.Types.Amount() { Total = input.Total }, + //Payer = new CreatePayTransactionNativeRequest.Types.Payer() { OpenId = input.OpenId } + Scene = new CreatePayTransactionNativeRequest.Types.Scene() { ClientIp = "127.0.0.1" } + }; + var response = await _wechatTenpayClient.ExecuteCreatePayTransactionNativeAsync(request); + if (!response.IsSuccessful()) + { + JSON.Serialize(response).LogInformation(); + throw Oops.Oh(response.ErrorMessage); + } + // 保存订单信息 + var wechatPay = new SysWechatPay() + { + AppId = _wechatPayOptions.AppId, + MerchantId = _wechatPayOptions.MerchantId, + OutTradeNumber = request.OutTradeNumber, + Description = input.Description, + Attachment = input.Attachment, + GoodsTag = input.GoodsTag, + Total = input.Total, + OpenId = input.OpenId, + TransactionId = "", + QrcodeContent = response.QrcodeUrl, + Tags = input.Tags, + BusinessId = input.BusinessId, + }; + await _sysWechatPayRep.InsertAsync(wechatPay); + return new CreatePayTransactionNativeOutput + { + OutTradeNumber = request.OutTradeNumber, + QrcodeUrl = response.QrcodeUrl + }; + } + + /// + /// 微信支付统一下单获取Id(服务商模式) 🔖 + /// + [DisplayName("微信支付统一下单获取Id(服务商模式)")] + public async Task CreatePayPartnerTransaction([FromBody] WechatPayTransactionInput input) + { + string outTradeNumber = DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000); // 微信需要的订单号(唯一) + + // 检查订单信息是否已存在(使用“商户交易单号+状态”唯一性判断) + var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OrderId == input.OrderId && u.OrderStatus == input.OrderStatus); + if (wechatPay != null) + { + outTradeNumber = wechatPay.OutTradeNumber; + } + + var request = new CreatePayPartnerTransactionJsapiRequest() + { + OutTradeNumber = outTradeNumber, + AppId = _wechatPayOptions.AppId, + MerchantId = _wechatPayOptions.MerchantId, + SubAppId = _wechatPayOptions.AppId, + SubMerchantId = _wechatPayOptions.MerchantId, + Description = input.Description, + Attachment = input.Attachment, + GoodsTag = input.GoodsTag, + ExpireTime = DateTimeOffset.Now.AddMinutes(10), + NotifyUrl = _payCallBackOptions.WechatPayUrl, + Amount = new CreatePayPartnerTransactionJsapiRequest.Types.Amount() { Total = input.Total }, + Payer = new CreatePayPartnerTransactionJsapiRequest.Types.Payer() { OpenId = input.OpenId } + }; + var response = await _wechatTenpayClient.ExecuteCreatePayPartnerTransactionJsapiAsync(request); + if (!response.IsSuccessful()) + throw Oops.Oh($"JSAPI 下单失败(状态码:{response.GetRawStatus()},错误代码:{response.ErrorCode},错误描述:{response.ErrorMessage})"); + if (wechatPay == null) + { + // 保存订单信息 + wechatPay = new SysWechatPay() + { + AppId = _wechatPayOptions.AppId, + MerchantId = _wechatPayOptions.MerchantId, + SubAppId = _wechatPayOptions.AppId, + SubMerchantId = _wechatPayOptions.MerchantId, + OutTradeNumber = request.OutTradeNumber, + Description = input.Description, + Attachment = input.Attachment, + GoodsTag = input.GoodsTag, + Total = input.Total, + OpenId = input.OpenId, + TransactionId = "" + }; + await _sysWechatPayRep.InsertAsync(wechatPay); + } + + return new CreatePayTransactionOutput + { + PrepayId = response.PrepayId, + OutTradeNumber = request.OutTradeNumber + }; + } + + /// + /// 获取支付订单详情 🔖 + /// + /// + /// + [DisplayName("获取支付订单详情")] + public async Task GetPayInfo(string tradeId) + { + return await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == tradeId); + } + + /// + /// 获取支付订单详情(微信接口) 🔖 + /// + /// + /// + [DisplayName("获取支付订单详情(微信接口)")] + public async Task GetPayInfoFromWechat(string tradeId) + { + var request = new GetPayTransactionByOutTradeNumberRequest(); + request.OutTradeNumber = tradeId; + var response = await _wechatTenpayClient.ExecuteGetPayTransactionByOutTradeNumberAsync(request); + // 修改订单支付状态 + var wechatPayOld = await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == response.OutTradeNumber + && u.MerchantId == response.MerchantId); + SysWechatPay wechatPayNew = null; + if (wechatPayOld != null) + wechatPayNew = wechatPayOld.DeepCopy(); + // 如果状态不一致就更新数据库中的记录 + if (wechatPayNew != null && wechatPayNew.TradeState != response.TradeState) + { + wechatPayNew.OpenId = response.Payer?.OpenId; + wechatPayNew.TransactionId = response.TransactionId; // 支付订单号 + wechatPayNew.TradeType = response.TradeType; // 交易类型 + wechatPayNew.TradeState = response.TradeState; // 交易状态 + wechatPayNew.TradeStateDescription = response.TradeStateDescription; // 交易状态描述 + wechatPayNew.BankType = response.BankType; // 付款银行类型 + if (response.Amount != null) + { + wechatPayNew.Total = response.Amount.Total; // 订单总金额 + wechatPayNew.PayerTotal = response.Amount.PayerTotal; // 用户支付金额 + } + if (response.SuccessTime.HasValue) + wechatPayNew.SuccessTime = response.SuccessTime.Value.DateTime; // 支付完成时间 + else + wechatPayNew.SuccessTime = DateTime.Now; + await _sysWechatPayRep.AsUpdateable(wechatPayNew).IgnoreColumns(true).ExecuteCommandAsync(); + } + if (wechatPayOld == null || wechatPayOld.TradeState != wechatPayNew.TradeState) + { + // 没必要等所有回调事件处理完再返回给微信,开一个Task执行 + _ = Task.Run(async () => + { + foreach (var eh in wechatPayEventHandlers) + { + try + { + //这里一定要用 DeepCopy 来创一个新的对象传进不,不然会被外面的 主线程改变就麻烦了 + if (!await eh.PayInforChanged(wechatPayOld, wechatPayNew.DeepCopy())) + break; + } + catch (Exception ex) + { + $"GetPayInfoFromWechat 中执行微信支付回调{eh.GetType().Name}出错".LogError(ex); + } + } + }); + } + // 下面这里创建一个新的对象,是因为不想把全部字段都返回 + var result = new SysWechatPay() + { + AppId = _wechatPayOptions.AppId, + MerchantId = _wechatPayOptions.MerchantId, + SubAppId = _wechatPayOptions.AppId, + SubMerchantId = _wechatPayOptions.MerchantId, + OutTradeNumber = request.OutTradeNumber, + Attachment = response.Attachment, + TransactionId = response.TransactionId, + TradeType = response.TradeType, // 交易类型 + TradeState = response.TradeState, // 交易状态 + TradeStateDescription = response.TradeStateDescription, // 交易状态描述 + BankType = response.BankType, // 付款银行类型 + SuccessTime = response.SuccessTime.HasValue ? response.SuccessTime.Value.DateTime : DateTime.Now // 支付完成时间 + }; + + return result; + } + + /// + /// 微信支付成功回调(商户直连) 🔖 + /// + /// + [AllowAnonymous] + [DisplayName("微信支付成功回调(商户直连)")] + public async Task PayCallBack() + { + using var ms = new MemoryStream(); + await App.HttpContext.Request.Body.CopyToAsync(ms); + var b = ms.ToArray(); + var callbackJson = Encoding.UTF8.GetString(b); + + var callbackModel = _wechatTenpayClient.DeserializeEvent(callbackJson); + if ("TRANSACTION.SUCCESS".Equals(callbackModel.EventType)) + { + var callbackResource = _wechatTenpayClient.DecryptEventResource(callbackModel); + + // 修改订单支付状态 + var wechatPayOld = await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == callbackResource.OutTradeNumber + && u.MerchantId == callbackResource.MerchantId); + if (wechatPayOld == null) return null; + var wechatPayNew = wechatPayOld.DeepCopy(); + if (callbackResource.Payer != null) + wechatPayNew.OpenId = callbackResource.Payer.OpenId; // 支付者标识 + wechatPayNew.TransactionId = callbackResource.TransactionId; // 支付订单号 + wechatPayNew.TradeType = callbackResource.TradeType; // 交易类型 + wechatPayNew.TradeState = callbackResource.TradeState; // 交易状态 + wechatPayNew.TradeStateDescription = callbackResource.TradeStateDescription; // 交易状态描述 + wechatPayNew.BankType = callbackResource.BankType; // 付款银行类型 + wechatPayNew.Total = callbackResource.Amount.Total; // 订单总金额 + wechatPayNew.PayerTotal = callbackResource.Amount.PayerTotal; // 用户支付金额 + wechatPayNew.SuccessTime = callbackResource.SuccessTime.DateTime; // 支付完成时间 + + await _sysWechatPayRep.AsUpdateable(wechatPayNew).IgnoreColumns(true).ExecuteCommandAsync(); + // 因为这个是回调给微信的,所以这里没必要等所有回调事件处理完再返回给微信,开一个Task执行 + if (wechatPayOld.TradeState != wechatPayNew.TradeState) + { + _ = Task.Run(async () => + { + foreach (var eh in wechatPayEventHandlers) + { + try + { + if (!await eh.PayInforChanged(wechatPayOld, wechatPayNew)) + break; + } + catch (Exception ex) + { + $"PayCallBack 中执行微信支付回调{eh.GetType().Name}出错".LogError(ex); + } + } + }); + } + return new WechatPayOutput() + { + Total = wechatPayNew.Total, + Attachment = wechatPayNew.Attachment, + GoodsTag = wechatPayNew.GoodsTag, + OrderId = long.Parse(wechatPayNew.OrderId) + }; + } + + return null; + } + + /// + /// 微信退款回调(商户直连) 🔖 + /// + /// + [AllowAnonymous] + [DisplayName("微信退款回调(商户直连)")] + public async Task RefundCallBack() + { + using var ms = new MemoryStream(); + await App.HttpContext.Request.Body.CopyToAsync(ms); + var b = ms.ToArray(); + var callbackJson = Encoding.UTF8.GetString(b); + + var callbackModel = _wechatTenpayClient.DeserializeEvent(callbackJson); + if ("REFUND.SUCCESS".Equals(callbackModel.EventType)) + { + // 参考:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/refund-result-notice.html + try + { + var callbackRefundResource = _wechatTenpayClient.DecryptEventResource(callbackModel); + // 修改订单支付状态 + var wechatRefund = await _sysWechatRefundRep.GetFirstAsync(u => u.OutRefundNumber == callbackRefundResource.OutRefundNumber); + if (wechatRefund == null) return null; + wechatRefund.RefundStatus = callbackRefundResource.RefundStatus; // 交易状态 + wechatRefund.SuccessTime = callbackRefundResource.SuccessTime.Value.DateTime; // 支付完成时间 + + await _sysWechatRefundRep.AsUpdateable(wechatRefund).IgnoreColumns(true).ExecuteCommandAsync(); + // 有退款,刷新一下订单状态(通过主动查询Wechat接口获取) + // 通过 GetPayInfoFromWechat 也会触发 WechatPayEventHandler,所以这个回调中不用主动调用 + await GetPayInfoFromWechat(callbackRefundResource.OutTradeNumber); + } + catch (Exception ex) + { + "微信退款回调时出错:".LogError(ex); + } + } + else + { + callbackModel.EventType.LogInformation(); + } + + return null; + } + + /// + /// 微信支付成功回调(服务商模式) 🔖 + /// + /// + [AllowAnonymous] + [DisplayName("微信支付成功回调(服务商模式)")] + public async Task PayPartnerCallBack() + { + using var ms = new MemoryStream(); + await App.HttpContext.Request.Body.CopyToAsync(ms); + var b = ms.ToArray(); + var callbackJson = Encoding.UTF8.GetString(b); + + var callbackModel = _wechatTenpayClient.DeserializeEvent(callbackJson); + if ("TRANSACTION.SUCCESS".Equals(callbackModel.EventType)) + { + var callbackResource = _wechatTenpayClient.DecryptEventResource(callbackModel); + + // 修改订单支付状态 + var wechatPayOld = await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == callbackResource.OutTradeNumber + && u.MerchantId == callbackResource.MerchantId); + + if (wechatPayOld == null) return; + var wechatPayNew = wechatPayOld.DeepCopy(); + //wechatPay.OpenId = callbackResource.Payer.OpenId; // 支付者标识 + //wechatPay.MerchantId = callbackResource.MerchantId; // 微信商户号 + //wechatPay.OutTradeNumber = callbackResource.OutTradeNumber; // 商户订单号 + wechatPayNew.TransactionId = callbackResource.TransactionId; // 支付订单号 + wechatPayNew.TradeType = callbackResource.TradeType; // 交易类型 + wechatPayNew.TradeState = callbackResource.TradeState; // 交易状态 + wechatPayNew.TradeStateDescription = callbackResource.TradeStateDescription; // 交易状态描述 + wechatPayNew.BankType = callbackResource.BankType; // 付款银行类型 + wechatPayNew.Total = callbackResource.Amount.Total; // 订单总金额 + wechatPayNew.PayerTotal = callbackResource.Amount.PayerTotal; // 用户支付金额 + wechatPayNew.SuccessTime = callbackResource.SuccessTime.DateTime; // 支付完成时间 + + await _sysWechatPayRep.AsUpdateable(wechatPayNew).IgnoreColumns(true).ExecuteCommandAsync(); + // 因为这个是回调给微信的,所以这里没必要等所有回调事件处理完再返回给微信,开一个Task执行 + if (wechatPayOld.TradeState != wechatPayNew.TradeState) + { + _ = Task.Run(async () => + { + foreach (var eh in wechatPayEventHandlers) + { + try + { + if (!await eh.PayInforChanged(wechatPayOld, wechatPayNew)) + break; + } + catch (Exception ex) + { + $"PayPartnerCallBack 中执行微信支付回调{eh.GetType().Name}出错".LogError(ex); + } + } + }); + } + } + } + + /// + /// 退款申请 🔖 + /// https://pay.weixin.qq.com/docs/merchant/apis/mini-program-payment/create.html + /// + /// + /// + [DisplayName("微信退款申请)")] + public async Task Refund(RefundRequestInput input) + { + var vechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == input.OutTradeNumber); + if (vechatPay == null) + throw Oops.Bah("没有相应支付记录"); + + var request = new CreateRefundDomesticRefundRequest() + { + OutTradeNumber = input.OutTradeNumber, + OutRefundNumber = "REFUND_" + DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff"), + NotifyUrl = _payCallBackOptions.WechatRefundUrl, + Amount = new CreateRefundDomesticRefundRequest.Types.Amount() + { + Total = input.Total, + Refund = input.Refund + }, + Reason = input.Reason, + }; + var response = await _wechatTenpayClient.ExecuteCreateRefundDomesticRefundAsync(request); + + if (!response.IsSuccessful()) + { + // 退款失败,该单可能已经退款了,所以主动查询微信接口更新状态 + try + { + await this.GetPayInfoFromWechat(input.OutTradeNumber); + } + catch { } + throw Oops.Oh($"JSAPI 退款申请失败(状态码:{response.GetRawStatus()},错误代码:{response.ErrorCode},错误描述:{response.ErrorMessage})"); + } + + var wechatRefund = await _sysWechatRefundRep.GetFirstAsync(u => u.OutTradeNumber == input.OutTradeNumber); + if (wechatRefund == null) + { + // 保存退款申请信息 + wechatRefund = new SysWechatRefund() + { + TransactionId = vechatPay.TransactionId, + OutTradeNumber = input.OutTradeNumber, + OutRefundNumber = request.OutRefundNumber, // 每笔付款只退一次,所以这里直接用付款单号 + Reason = request.Reason, + Refund = input.Refund, + RefundId = response.RefundId, + Total = input.Total, + NotifyUrl = _payCallBackOptions.WechatRefundUrl, + OrderId = input.OrderId, + RefundStatus = input.OrderStatus, + MerchantGoodsId = input.MerchantGoodsId, + GoodsName = input.GoodsName, + UnitPrice = input.UnitPrice, + RefundAmount = input.RefundAmount, + RefundQuantity = input.RefundQuantity, + Attachment = input.Attachment, + Remark = input.Remark + }; + await _sysWechatRefundRep.InsertAsync(wechatRefund); + // 发送了退款请求也要更新原定单的状态(从微信查询) + await this.GetPayInfoFromWechat(input.OutTradeNumber); + } + } + + /// + /// 查询单笔退款(通过商户退款单号) 🔖 + /// https://pay.weixin.qq.com/docs/merchant/apis/mini-program-payment/query-by-out-refund-no.html + /// + /// + /// + [DisplayName("微信查询单笔退款)")] + public async Task GetRefundByOutRefundNumber(string outRefundNumber) + { + var request = new GetRefundDomesticRefundByOutRefundNumberRequest() + { + OutRefundNumber = outRefundNumber + }; + return await _wechatTenpayClient.ExecuteGetRefundDomesticRefundByOutRefundNumberAsync(request); + } + + /// + /// 微信支付订单号查询(校正) 🔖 + /// https://api.mch.weixin.qq.com/v3/pay/transactions/id/{transaction_id} + /// + /// + /// + [DisplayName("微信支付订单号查询(校正)")] + public async Task GetPayTransactionByIdAsync(string transactionId) + { + if (string.IsNullOrEmpty(transactionId)) + throw Oops.Oh("TransactionId 不能为空"); + + if (string.IsNullOrEmpty(_wechatPayOptions.MerchantId) || string.IsNullOrEmpty(_wechatPayOptions.MerchantCertificateSerialNumber)) + throw Oops.Oh("商户号或证书序列号不能为空,请检查支付配置"); + + var request = new GetPayTransactionByIdRequest() + { + MerchantId = _wechatPayOptions.MerchantId, + TransactionId = transactionId, + WechatpaySerialNumber = _wechatPayOptions.MerchantCertificateSerialNumber + }; + var response = await _wechatTenpayClient.ExecuteGetPayTransactionByIdAsync(request); + if (response.TradeState == "SUCCESS" || response.TradeState == "CLOSED" || response.TradeState == "NOTPAY") + { + // 修正订单支付状态 + var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.TransactionId == request.TransactionId && u.MerchantId == request.MerchantId); + if (wechatPay != null && string.IsNullOrEmpty(wechatPay.TradeState)) + { + wechatPay.TradeType = response.TradeType; // 交易类型 + wechatPay.TradeState = response.TradeState; // 交易状态 + wechatPay.TradeStateDescription = response.TradeStateDescription; // 交易状态描述 + wechatPay.OpenId = response.Payer?.OpenId;// 付款用户OpenId + wechatPay.BankType = response.BankType; // 付款银行类型 + wechatPay.PayerTotal = response.Amount?.PayerTotal; // 用户支付金额 + wechatPay.SuccessTime = response.SuccessTime?.DateTime; // 支付完成时间 + await _sysWechatPayRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync(); + return wechatPay.Adapt(); + } + } + return response.Adapt(); + } + + /// + /// 商户订单号查询(校正) 🔖 + /// https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no} + /// + /// + /// + [DisplayName("微信商户订单号查询(校正)")] + public async Task GetPayTransactionByOutTradeNumberAsync(string outTradeNumber) + { + if (string.IsNullOrEmpty(outTradeNumber)) + throw Oops.Oh("商户订单号(OutTradeNumber)不能为空"); + + if (string.IsNullOrEmpty(_wechatPayOptions.MerchantId) || string.IsNullOrEmpty(_wechatPayOptions.MerchantCertificateSerialNumber)) + throw Oops.Oh("商户号或证书序列号不能为空,请检查支付配置"); + + var request = new GetPayTransactionByOutTradeNumberRequest() + { + MerchantId = _wechatPayOptions.MerchantId, + OutTradeNumber = outTradeNumber, + WechatpaySerialNumber = _wechatPayOptions.MerchantCertificateSerialNumber, + }; + var response = await _wechatTenpayClient.ExecuteGetPayTransactionByOutTradeNumberAsync(request); + if (response.TradeState == "SUCCESS" || response.TradeState == "CLOSED" || response.TradeState == "NOTPAY") + { + // 修正订单支付状态 + var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == outTradeNumber && u.MerchantId == request.MerchantId); + if (wechatPay != null && string.IsNullOrEmpty(wechatPay.TradeState)) + { + wechatPay.TransactionId = response.TransactionId; // 支付订单号 + wechatPay.TradeType = response.TradeType; // 交易类型 + wechatPay.TradeState = response.TradeState; // 交易状态 + wechatPay.TradeStateDescription = response.TradeStateDescription; // 交易状态描述 + wechatPay.OpenId = response.Payer?.OpenId;// 付款用户OpenId + wechatPay.BankType = response.BankType; // 付款银行类型 + wechatPay.PayerTotal = response.Amount?.PayerTotal; // 用户支付金额 + wechatPay.SuccessTime = response.SuccessTime?.DateTime; // 支付完成时间 + await _sysWechatPayRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync(); + return wechatPay.Adapt(); + } + } + return response.Adapt(); + } + + /// + /// 获取支付记录分页列表 🔖 + /// + /// PageSysWechatPayInput + /// + [DisplayName("获取支付记录分页列表")] + public async Task> PageAsync(PageSysWechatPayInput input) + { + var query = _sysWechatPayRep.AsQueryable() + .WhereIF(!string.IsNullOrWhiteSpace(input.OrderId), u => u.OrderId == input.OrderId) + .WhereIF(!string.IsNullOrWhiteSpace(input.OrderStatus), u => u.OrderStatus == input.OrderStatus) + .WhereIF(!string.IsNullOrWhiteSpace(input.OutTradeNumber), u => u.OutTradeNumber.Contains(input.OutTradeNumber.Trim())); + + if (input.SuccessTimeRange != null && input.SuccessTimeRange.Count > 0) + { + DateTime? start = input.SuccessTimeRange[0]; + query.WhereIF(start.HasValue, u => u.SuccessTime > start); + if (input.SuccessTimeRange.Count > 1 && input.SuccessTimeRange[1].HasValue) + { + var end = input.SuccessTimeRange[1].Value.AddDays(1); + query.Where(u => u.SuccessTime < end); + } + } + if (input.ExpireTimeRange != null && input.ExpireTimeRange.Count > 0) + { + DateTime? start = input.ExpireTimeRange[0]; + query.WhereIF(start.HasValue, u => u.ExpireTime > start); + if (input.ExpireTimeRange.Count > 1 && input.ExpireTimeRange[1].HasValue) + { + var end = input.ExpireTimeRange[1].Value.AddDays(1); + query.Where(u => u.ExpireTime < end); + } + } + query.OrderByDescending(u => u.CreateTime); + return await query.ToPagedListAsync(input.Page, input.PageSize); + } + + /// + /// 根据支付Id获取退款信息列表 🔖 + /// + /// + /// + /// + [DisplayName("根据支付Id获取退款信息列表")] + public async Task> GetRefundList([FromQuery] string transactionId, [FromQuery] string outTradeNumber) + { + return await _sysWechatRefundRep.AsQueryable() + .WhereIF(!string.IsNullOrEmpty(transactionId), u => u.TransactionId == transactionId) + .WhereIF(!string.IsNullOrEmpty(outTradeNumber), u => u.OutTradeNumber == outTradeNumber) + .ToListAsync(); + } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs index 6fc34798..f9c5ea95 100644 --- a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs +++ b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs @@ -23,6 +23,8 @@ public static class SqlSugarSetup // 自定义雪花Id算法 StaticConfig.CustomSnowFlakeFunc = YitIdHelper.NextId; + // 注册 MongoDb + InstanceFactory.CustomAssemblies = [typeof(SqlSugar.MongoDb.MongoDbProvider).Assembly]; // 配置字符串表达式 StaticConfig.DynamicExpressionParserType = typeof(DynamicExpressionParser); StaticConfig.DynamicExpressionParsingConfig = new ParsingConfig @@ -599,8 +601,16 @@ public static class SqlSugarSetup var sql = viewType.GetMethod(nameof(ISqlSugarView.GetQueryableSqlString))?.Invoke(Activator.CreateInstance(viewType), [dbProvider]) as string; if (string.IsNullOrWhiteSpace(sql)) throw new Exception("视图初始化Sql语句不能为空"); - // 创建视图 - dbProvider.Ado.ExecuteCommand($"CREATE VIEW {entityInfo.DbTableName} AS " + Environment.NewLine + " " + sql); + try + { + // 创建视图 + dbProvider.Ado.ExecuteCommand($"CREATE VIEW {entityInfo.DbTableName} AS " + Environment.NewLine + " " + sql); + } + catch (Exception ex) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine($"初始化视图 {viewType.FullName,-58} ({config.ConfigId} - 失败,{ex.Message})"); + } // 停止计时 stopWatch.Stop(); diff --git a/Admin.NET/Admin.NET.Core/Utils/CommonHelper.cs b/Admin.NET/Admin.NET.Core/Utils/CommonHelper.cs index 965c38d1..3d1f1a8d 100644 --- a/Admin.NET/Admin.NET.Core/Utils/CommonHelper.cs +++ b/Admin.NET/Admin.NET.Core/Utils/CommonHelper.cs @@ -52,7 +52,7 @@ public static class CommonHelper string noLetters = Regex.Replace(version, "[a-zA-Z]", ""); // 2. 按 '.' 分割版本号 - string[] parts = noLetters.Split(['.'], StringSplitOptions.RemoveEmptyEntries); + string[] parts = noLetters.Split('.', StringSplitOptions.RemoveEmptyEntries); // 3. 确保至少有3部分,不足则补 "0" if (parts.Length < 3) diff --git a/Admin.NET/Admin.NET.Core/Utils/PathTreeBuilder.cs b/Admin.NET/Admin.NET.Core/Utils/PathTreeBuilder.cs index 7fcffe4b..1d2da24d 100644 --- a/Admin.NET/Admin.NET.Core/Utils/PathTreeBuilder.cs +++ b/Admin.NET/Admin.NET.Core/Utils/PathTreeBuilder.cs @@ -31,7 +31,7 @@ public class PathTreeBuilder foreach (var path in paths) { - var parts = path.Split(['/'], StringSplitOptions.RemoveEmptyEntries); + var parts = path.Split('/', StringSplitOptions.RemoveEmptyEntries); TreeNode currentNode = root; foreach (var part in parts) diff --git a/Admin.NET/Admin.NET.Core/Utils/System/CamelCaseValueConverter.cs b/Admin.NET/Admin.NET.Core/Utils/System/CamelCaseValueConverter.cs new file mode 100644 index 00000000..f7ed3665 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Utils/System/CamelCaseValueConverter.cs @@ -0,0 +1,45 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; + +namespace Admin.NET.Core; + +/// +/// 首字母小写(驼峰样式)转换 +/// +public class CamelCaseValueConverter : JsonConverter +{ + private static readonly CamelCaseNamingStrategy NamingStrategy = new(true, true); + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (value == null) + { + writer.WriteNull(); + return; + } + + if (typeof(IEnumerable).IsAssignableFrom(value.GetType())) + serializer.Serialize(writer, ((IEnumerable)value).Select(u => NamingStrategy.GetPropertyName(u, false))); + else + writer.WriteValue(NamingStrategy.GetPropertyName(value + "", false)); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + return reader.Value; + } + + public override bool CanConvert(Type objectType) + { + if (objectType == typeof(string) || typeof(IEnumerable).IsAssignableFrom(objectType)) + return true; + + return false; + } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Web.Core/Admin.NET.Web.Core.csproj b/Admin.NET/Admin.NET.Web.Core/Admin.NET.Web.Core.csproj index 793ce343..b8e43fa7 100644 --- a/Admin.NET/Admin.NET.Web.Core/Admin.NET.Web.Core.csproj +++ b/Admin.NET/Admin.NET.Web.Core/Admin.NET.Web.Core.csproj @@ -12,7 +12,7 @@ - + diff --git a/Admin.NET/Admin.NET.Web.Core/Startup.cs b/Admin.NET/Admin.NET.Web.Core/Startup.cs index 74005d85..dcba6139 100644 --- a/Admin.NET/Admin.NET.Web.Core/Startup.cs +++ b/Admin.NET/Admin.NET.Web.Core/Startup.cs @@ -24,6 +24,7 @@ using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Hosting; using MQTTnet.AspNetCore; using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; using OnceMi.AspNetCore.OSS; using RabbitMQ.Client; using SixLabors.ImageSharp.Web.DependencyInjection; @@ -59,6 +60,10 @@ public class Startup : AppStartup // 若请求 Url 包含 token 参数,则设置 Token 值 if (httpContext.Request.Query.ContainsKey("token")) context.Token = httpContext.Request.Query["token"]; + // 若请求 Url 包含 access_token 参数,则设置 Token 值 + // 兼容 SignalR 通过 accessTokenFactory 传入的 token 值 .withUrl("/hubs/xxx", { accessTokenFactory: () => this.loginToken }) + if (httpContext.Request.Query.ContainsKey("access_token")) + context.Token = httpContext.Request.Query["access_token"]; return Task.CompletedTask; } }; @@ -133,6 +138,12 @@ public class Startup : AppStartup //options.JsonSerializerOptions.Converters.AddDateTimeTypeConverters("yyyy-MM-dd HH:mm:ss", localized: true); // 时间格式 }); + // 增加字典Key小写处理序列化配置选项 + var camelCaseDictionaryKeyContractJsonSetting = new JsonSerializerSettings(); + SetNewtonsoftJsonSetting(camelCaseDictionaryKeyContractJsonSetting); + camelCaseDictionaryKeyContractJsonSetting.ContractResolver = new CamelCasePropertyNamesContractResolver(); // 首字母小写(驼峰样式),字典 Key 也会转换为驼峰样式 + services.AddUnifyJsonOptions("CamelCaseDictionaryKey", camelCaseDictionaryKeyContractJsonSetting); + // SqlSugar services.AddSqlSugar(); @@ -412,7 +423,7 @@ public class Startup : AppStartup app.UseScheduleUI(options => { options.RequestPath = "/schedule"; // 必须以 / 开头且不以 / 结尾 - options.DisableOnProduction = true; // 是否在生产环境中关闭 + options.DisableOnProduction = false; // 是否在生产环境中关闭 options.DisplayEmptyTriggerJobs = true; // 是否显示空作业触发器的作业 options.DisplayHead = false; // 是否显示页头 options.DefaultExpandAllJobs = false; // 是否默认展开所有作业 diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_Mid.cs.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_Mid.cs.vm index ded75017..b0ea8ee1 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_Mid.cs.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_Mid.cs.vm @@ -64,7 +64,7 @@ public partial class @(@Model.ClassName)Mid @:.WhereIF(!string.IsNullOrWhiteSpace(input.@column.PropertyName), u => u.@(@column.PropertyName) @column.QueryType input.@(@column.PropertyName)) } }else if(@column.NetType?.TrimEnd('?') == "int" || @column.NetType?.TrimEnd('?') == "long"){ - @:.WhereIF(input.@column.PropertyName>0, u => u.@(@column.PropertyName) @column.QueryType input.@(@column.PropertyName)) + @:.WhereIF(input.@column.PropertyName>0, u => (int)u.@(@column.PropertyName) @column.QueryType input.@(@column.PropertyName)) }else if(@column.NetType?.TrimEnd('?') == "DateTime" && @column.QueryType == "~"){ @:.WhereIF(input.@(@column.PropertyName)Range != null && input.@(@column.PropertyName)Range.Length == 2, u => u.@(@column.PropertyName) >= input.@(@column.PropertyName)Range[0] && u.@(@column.PropertyName) <= input.@(@column.PropertyName)Range[1]) }else if(@column.NetType?.TrimEnd('?').EndsWith("Enum") == true) { diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_Service.cs.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_Service.cs.vm index 863d58ac..85251b23 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_Service.cs.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_Service.cs.vm @@ -82,7 +82,7 @@ public partial class @(@Model.ClassName)Service : IDynamicApiController, ITransi /// /// /// - [ApiDescriptionSettings(Name = "page", Description = "分页查询", Order = 1000), HttpPost] + [ApiDescriptionSettings(Name = "Page", Description = "分页查询", Order = 1000), HttpPost] [DisplayName("分页查询@(@Model.BusName)")] public async Task> Page(Page@(@Model.ClassName)Input input) { @@ -98,7 +98,7 @@ public partial class @(@Model.ClassName)Service : IDynamicApiController, ITransi /// /// /// - [ApiDescriptionSettings(Name = "add", Description = "增加@(@Model.BusName)", Order = 990), HttpPost] + [ApiDescriptionSettings(Name = "Add", Description = "增加@(@Model.BusName)", Order = 990), HttpPost] [DisplayName("增加@(@Model.BusName)")] public async Task Add(Add@(@Model.ClassName)Input input) { @@ -120,7 +120,7 @@ public partial class @(@Model.ClassName)Service : IDynamicApiController, ITransi /// /// /// - [ApiDescriptionSettings(Name = "delete", Description = "删除(@Model.BusName)", Order = 980), HttpPost] + [ApiDescriptionSettings(Name = "Delete", Description = "删除(@Model.BusName)", Order = 980), HttpPost] [DisplayName("删除@(@Model.BusName)")] public async Task Delete(Delete@(@Model.ClassName)Input input) { @@ -138,7 +138,7 @@ if (@column.ColumnKey == "True"){ /// /// /// - [ApiDescriptionSettings(Name = "update", Description = "更新@(@Model.BusName)", Order = 970), HttpPost] + [ApiDescriptionSettings(Name = "Update", Description = "更新@(@Model.BusName)", Order = 970), HttpPost] [DisplayName("更新@(@Model.BusName)")] public async Task Update(Update@(@Model.ClassName)Input input) { @@ -160,7 +160,7 @@ if (@column.ColumnKey == "True"){ /// /// /// - [ApiDescriptionSettings(Name = "detail", Description = "获取@(@Model.BusName)", Order = 960), HttpGet] + [ApiDescriptionSettings(Name = "Detail", Description = "获取@(@Model.BusName)", Order = 960), HttpGet] [DisplayName("获取@(@Model.BusName)")] public async Task<@(@Model.ClassName)> Detail([FromQuery] QueryById@(@Model.ClassName)Input input) { @@ -170,7 +170,7 @@ if (@column.ColumnKey == "True"){ } } } - + /*HJ:不要,有分页了,列表多余的 /// /// 获取@(@Model.BusName)列表 /// @@ -182,7 +182,9 @@ if (@column.ColumnKey == "True"){ { return await @(@Model.ClassName)Mid.GetQuery(_@(@Model.LowerClassName)Rep, input).OrderBuilder(input).ToListAsync(); } + */ + /*HJ:不要这应该在视图里,或者用ReZero里用 /// /// 获取@(@Model.BusName) /// @@ -216,7 +218,9 @@ if (@column.ColumnKey == "True"){ }); return await querystats.ToListAsync(); } - + */ + + /*HJ:不要危险度大,容易SQL注入,且不符合规范 /// /// 根据输入参数获取@(@Model.BusName)统计 /// 支持双模式聚合配置: @@ -299,6 +303,8 @@ if (@column.ColumnKey == "True"){ @:return await query.ToListAsync(); } } + + */ @foreach (var column in Model.TableField){ if(@column.EffectType == "ForeignKey" && (@column.WhetherAddUpdate == "Y" || column.QueryWhether == "Y")){ @@ -328,24 +334,84 @@ if(@column.EffectType == "Upload"){ @:/// @:/// @:/// - @:[ApiDescriptionSettings(Name = "upload@(@column.PropertyName)", Description = "上传@(@column.ColumnComment)", Order = 930), HttpPost] + @:[ApiDescriptionSettings(Name = "Upload@(@column.PropertyName)", Description = "上传@(@column.ColumnComment)", Order = 930), HttpPost] @:[DisplayName("上传@(@column.ColumnComment)")] @:public async Task Upload@(@column.PropertyName)([Required] IFormFile file) @:{ @:var service = App.GetRequiredService(); - @:return await service.UploadFile(new UploadFileInput { File = file, Path = "upload/@(@column.PropertyName)" }); + @:return await service.UploadFile(new UploadFileInput { File = file}, "upload/@(@column.PropertyName)" ); @:} } } @foreach (var column in Model.TableField){ + if(@column.EffectType == "ApiTreeSelector" && !definedObjects.ContainsKey("@(@column.FkEntityName)Tree")){ - @{definedObjects.Add("@(@column.FkEntityName)Tree", 1);} - @:[ApiDescriptionSettings(Name = "@(LowerFirstLetter(@column.FkEntityName))Tree", Description = "获取@(@column.ColumnComment)列表", Order = 920), HttpGet] - @:[DisplayName("获取@(@column.FkEntityName)Tree")] - @:public async Task @(@column.FkEntityName)Tree() + @:/// + @:/// 获取@(@Model.BusName)树列表 + @:/// + @:/// + @:/// + @:[ApiDescriptionSettings(Name = "Tree", Description = "获取@(@Model.BusName)树列表", Order = 960), HttpPost] + @:[DisplayName("获取@(@Model.BusName)树列表")] + @:public async Task Tree(Page@(@Model.ClassName)Input input) @:{ - @:return await _@(@Model.LowerClassName)Rep.Context.Queryable<@(@column.FkEntityName)>().Select<@(@column.FkEntityName)Output>().ToTreeAsync(u => u.Children, u => u.@(@column.PidColumn), 0); + + @:// 有筛选条件时返回list列表(防止构造不出树) + @:var isSearch=false; + + foreach (var columnTree in Model.TableField){ + if (@columnTree.QueryWhether == "Y"){ + if (@columnTree.NetType?.TrimEnd('?') == "string"){ + @:if(!string.IsNullOrWhiteSpace(input.@columnTree.PropertyName))isSearch=true; + + }else if((@columnTree.NetType?.TrimEnd('?') == "int" || @columnTree.NetType?.TrimEnd('?') == "long")){ + @:if(input.@columnTree.PropertyName>0)isSearch=true; + + }else if((@columnTree.NetType?.TrimEnd('?') == "DateTime" && @columnTree.QueryType == "~")){ + @:if(input.@(@columnTree.PropertyName)Range != null)isSearch=true; + } }} + + + @:if (isSearch||!string.IsNullOrEmpty(input.SearchKey?.Trim())) + @:{ + + @:return await _@(@Model.LowerClassName)Rep.AsQueryable() + + @{string conditionFlag = "";} + @if (haveLikeCdt) { + @:.WhereIF(!string.IsNullOrEmpty(input.SearchKey?.Trim()), u => + @foreach (var columnTree in Model.TableField){ + if (@columnTree.QueryWhether == "Y" && columnTree.QueryType == "like"){ + @:@(conditionFlag)u.@(@columnTree.PropertyName).Contains(input.SearchKey.Trim()) + conditionFlag="|| "; + } + } + @:) + } + foreach (var columnTree in Model.TableField){ + if (@columnTree.QueryWhether == "Y"){if (@columnTree.NetType?.TrimEnd('?') == "string"){if(@columnTree.QueryType == "like"){ + @:.WhereIF(!string.IsNullOrWhiteSpace(input.@columnTree.PropertyName), u => u.@(@columnTree.PropertyName).Contains(input.@(@columnTree.PropertyName).Trim())) + }else{ + @:.WhereIF(!string.IsNullOrWhiteSpace(input.@columnTree.PropertyName), u => u.@(@columnTree.PropertyName) @columnTree.QueryType input.@(@columnTree.PropertyName)) + }}else if(@columnTree.NetType?.TrimEnd('?') == "int" || @columnTree.NetType?.TrimEnd('?') == "long"){ + @:.WhereIF(input.@columnTree.PropertyName>0, u => (int)u.@(@columnTree.PropertyName) @columnTree.QueryType input.@(@columnTree.PropertyName)) + }else if(@columnTree.NetType?.TrimEnd('?') == "DateTime" && @columnTree.QueryType == "~"){ + @:.WhereIF(input.@(@columnTree.PropertyName)Range != null && input.@(@columnTree.PropertyName)Range.Length == 2, u => u.@(@columnTree.PropertyName) >= input.@(@columnTree.PropertyName)Range[0] && u.@(@columnTree.PropertyName) <= input.@(@columnTree.PropertyName)Range[1]) + }else if(@columnTree.NetType?.TrimEnd('?').EndsWith("Enum") == true) { + @:.WhereIF(input.@(@columnTree.PropertyName).HasValue, u => u.@(@columnTree.PropertyName) @columnTree.QueryType input.@(@columnTree.PropertyName)) + }}} + //HJ @:.OrderBy(u => u.OrderNo) + @:.OrderByDescending(u => u.Id) + @:.Distinct().ToListAsync(); + @:} + + @:// 无筛选条件时返回树列表 + @:return await _@(@Model.LowerClassName)Rep.AsQueryable() + //HJ @:.OrderBy(u => u.OrderNo) + @:.OrderByDescending(u => u.Id) + @:.ToTreeAsync(u => u.Children, u => u.Pid, 0, u => u.Id); + @:} } } diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_List.vue.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_List.vue.vm index 9ed42a6e..08857bd9 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_List.vue.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_List.vue.vm @@ -202,39 +202,33 @@ import { onMounted, reactive, ref } from 'vue'; import { ElMessageBox, ElMessage } from "element-plus"; import { useUserInfo } from '/@@/stores/userInfo'; - import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table'; import { useVxeTable } from '/@@/hooks/useVxeTableOptionsHook'; import { Local } from '/@@/utils/storage'; +import { auth } from '/@@/utils/authFunction'; +import EditDialog from '/@@/views/@(@Model.PagePath)/@(@Model.LowerClassName)/component/edit.vue'; +import ModifyRecord from '/@@/components/table/modifyRecord.vue'; @if(@Model.TableField.Any(x=>x.EffectType == "DatePicker")){ +@:// 日历控件 @:import { formatDate } from '/@@/utils/formatTime'; } @if(@Model.PrintType != "off"){ -@:// 推荐设置操作 width 为 200 +@://打印控件 @:import { hiprint } from 'vue-plugin-hiprint'; -@:import { SysPrintApi } from '/@@/api-services/api'; -@:import { SysPrint } from '/@@/api-services/models'; -} -// 子窗口 -@if(@Model.PrintType != "off") { +@:import { SysPrintApi } from '/@@/api-monkey/api'; +@:import { SysPrint } from '/@@/api-monkey/models'; @: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'; - -// 接口 @: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.ClassName), delete@(@Model.ClassName), get@(@Model.ClassName)TotalSum } from '/@@/api/@(@Model.PagePath)/@(@Model.LowerClassName)'; foreach (var column in Model.QueryWhetherList){ if(@column.EffectType == "ForeignKey"){ @@ -246,24 +240,26 @@ foreach (var column in Model.QueryWhetherList){ } } -// 子窗口对象 +//基础变量 const xGrid = ref(); -@if(@Model.PrintType != "off") { -@:const printDialogRef = ref>(); -} const editDialogRef = ref>(); const userStore = useUserInfo(); - +@if(@Model.PrintType != "off") { +@://打印控件 +@:const printDialogRef = ref>(); +} @if(@Model.TableField.Any(x=>x.EffectType == "ConstSelector")){ +@://常量控件 @:const codeToName = userStore.codeToName; } @if(@Model.TableField.Any(x=>x.EffectType == "DictSelector") || @Model.TableField.Any(x=>x.EffectType == "EnumSelector")){ +@//字典枚举控件 @:const dc = userStore.getDictItemByValue; @:const dv = userStore.getDictItemByLabel; @:const dl = userStore.getDictDataByCode; } -// 变量 +// 变量赋值 const state = reactive({ showAdvanceQueryUI: false, queryParams: { @@ -338,9 +334,9 @@ const checkTableColumnVisible = (tableColumnName: any) => { } } @if(@Model.TableField.Any(t => t.ColumnName == "CreateTime") && @Model.TableField.Any(t => t.ColumnName == "UpdateTime") && @Model.TableField.Any(t => t.ColumnName == "CreateUserId")){ - @:{ title: '修改记录', width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } }, + @:{ field: 'record', title: '修改记录', width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } }, } - { title: '操作', fixed: 'right', width: 180, showOverflow: true, slots: { default: 'row_buttons' } }, + { field: 'buttons', title: '操作', fixed: 'right', width: 180, showOverflow: true, slots: { default: 'row_buttons' } }, ], @if(@Model.TableField.Any(x=>x.Statistical == "Y")){ @:footerMethod: ({ columns, data }) => { @@ -426,6 +422,7 @@ const listhandleQuery= async (qparams: any) => { if(qparams) state.queryParams=qparams; await handleQuery(true); }; + // 重置操作 const resetQuery = async () => { state.queryParams.searchKey = undefined; @@ -523,6 +520,10 @@ const handleDelete = (row: any) => { state.localPageParam.defaultSort = { field: field, order: order!, descStr: 'desc' }; Local.set(localPageParamKey, state.localPageParam); }, + // 双击行事件 + async cellDblclick({ row }) { + if (auth('@(@Model.LowerClassName)/update')) await handleEdit(row); + }, }; @foreach (var column in Model.QueryWhetherList) { @@ -564,13 +565,3 @@ const listClick = (row: any,column:any) => { defineExpose({ listhandleQuery }); - diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_TreeList.vue.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_TreeList.vue.vm index 1ba2199d..50a475bd 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_TreeList.vue.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_TreeList.vue.vm @@ -52,7 +52,7 @@ - + @@ -60,7 +60,7 @@ - + @@ -179,9 +179,9 @@ } } } - + - - - diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_editDialog.vue.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_editDialog.vue.vm index d131a524..5c7cdf73 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_editDialog.vue.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_editDialog.vue.vm @@ -134,7 +134,7 @@ @::src="state.ruleForm.@(@column.LowerPropertyName)" @:@@click="state.ruleForm.@(@column.LowerPropertyName)=''" @:style="width: 100%; height: 100%; object-fit: contain"/> - @: + @: @@ -146,6 +146,13 @@ + }else if(@column.EffectType == "RichTextEditor"){ + //HJ:添加富文本插件 + @: + @: + @: + + }else{ } } @@ -163,30 +170,25 @@ - - - - diff --git a/Admin.NET/Plugins/Admin.NET.Plugin.PaddleOCR/Admin.NET.Plugin.PaddleOCR.csproj b/Admin.NET/Plugins/Admin.NET.Plugin.PaddleOCR/Admin.NET.Plugin.PaddleOCR.csproj index 2d5cc8bc..35f74ed6 100644 --- a/Admin.NET/Plugins/Admin.NET.Plugin.PaddleOCR/Admin.NET.Plugin.PaddleOCR.csproj +++ b/Admin.NET/Plugins/Admin.NET.Plugin.PaddleOCR/Admin.NET.Plugin.PaddleOCR.csproj @@ -25,8 +25,8 @@ - - + + diff --git a/README.md b/README.md index 5271ffb3..4281bd61 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ ## 🎁框架介绍 -基于 .NET 8 (Furion/SqlSugar) 实现的通用权限开发框架,前端采用 Vue3/Element-plus,代码简洁、易扩展。整合最新技术,模块插件式开发,前后端分离,开箱即用。集成多租户、缓存、数据校验、鉴权、事件总线、动态API、通讯、远程请求、任务调度、打印等众多黑科技。 +Admin.NET 是基于 .NET6 (Furion/SqlSugar) 实现的通用权限开发框架,前端采用 Vue3+Element-plus+Vite5,整合众多优秀技术和框架,模块插件式开发。集成多租户、缓存、数据校验、鉴权、事件总线、动态API、通讯、远程请求、任务调度、打印等众多黑科技。代码结构简单清晰,注释详尽,易于上手与二次开发,即便是复杂业务逻辑也能迅速实现,真正实现“开箱即用”。 -前后端分离架构模式,内置国密算法(SM2/SM4),软件层面完全符合等保测评和信创要求,同时实现国产化机型、操作系统(麒麟)、中间件、数据库(达梦、人大金仓等)等适配! +面向中小企业快速开发平台框架,框架采用主流技术开发设计,前后端分离架构模式。完美适配国产化软硬件环境,支持国产中间件、国产数据库、麒麟操作系统、Windows、Linux部署使用;集成国密加解密插件,使用SM2、SM3、SM4等国密算法进行签名、数据完整性保护;软件层面全面遵循等级保护测评要求,完全符合等保、密评要求。 ``` 超高人气的框架(Furion)配合高性能超简单的ORM(SqlSugar)加持,阅历痛点,相见恨晚!让 .NET 开发更简单,更通用,更流行! @@ -22,8 +22,9 @@ 1. 支持各种数据库,后台配置文件自行修改(自动生成数据库及种子数据) 2. 前端运行步骤:1、安装依赖pnpm install 2、运行pnpm run dev 3、打包pnpm run build 3. QQ交流群1:[87333204](https://jq.qq.com/?_wv=1027&k=1t8iqf0G) QQ交流群2:[252381476](https://jq.qq.com/?_wv=1027&k=IkzihDcL) -4. 演示环境1:http://101.43.53.74:5005/dist/index.html -5. [GitHub 镜像地址](https://github.com/zuohuaijun/Admin.NET.git) [Gitee 镜像地址](https://gitee.com/zuohuaijun/Admin.NET.git) +4. 演示环境1:https://demo.adminnet.top 账号:superadmin 密码:Admin.NET++010101 +5. [GitHub 镜像地址](https://github.com/zuohuaijun/Admin.NET.git) [Gitee 镜像地址](https://gitee.com/zuohuaijun/Admin.NET.git) [GitCode 镜像地址](https://gitcode.com/zuohuaijun/Admin.NET.git) +6. 在线文档 [https://adminnet.top/](https://adminnet.top/) ## 📙开发流程 ```bash diff --git a/Web/package.json b/Web/package.json index cccff5ec..3d63bb62 100644 --- a/Web/package.json +++ b/Web/package.json @@ -2,7 +2,7 @@ "name": "admin.net.pro", "type": "module", "version": "2.4.33", - "lastBuildTime": "2025.06.20", + "lastBuildTime": "2025.07.21", "description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架", "author": "zuohuaijun", "license": "MIT", @@ -24,9 +24,9 @@ "@vue-office/docx": "^1.6.2", "@vue-office/excel": "^1.7.14", "@vue-office/pdf": "^2.0.9", - "@vueuse/core": "^13.4.0", + "@vueuse/core": "^13.5.0", "@vxe-ui/plugin-export-xlsx": "^4.2.2", - "@vxe-ui/plugin-render-element": "^4.0.11", + "@vxe-ui/plugin-render-element": "^4.0.13", "@wangeditor/editor": "^5.1.23", "@wangeditor/editor-for-vue": "^5.1.12", "animate.css": "^4.1.1", @@ -38,9 +38,9 @@ "echarts": "^5.6.0", "echarts-gl": "^2.0.9", "echarts-wordcloud": "^2.1.0", - "element-plus": "^2.10.2", + "element-plus": "^2.10.4", "exceljs": "^4.4.0", - "ezuikit-js": "^8.1.10", + "ezuikit-js": "^8.1.12", "flag-icons": "^7.5.0", "franc": "^6.2.0", "gcoord": "^1.0.7", @@ -51,10 +51,10 @@ "jwchat": "^2.0.3", "lodash-es": "^4.17.21", "magic-string": "^0.30.17", - "md-editor-v3": "^5.7.0", + "md-editor-v3": "^5.8.2", "mitt": "^3.0.1", "monaco-editor": "^0.52.2", - "mqtt": "^5.13.1", + "mqtt": "^5.13.3", "nprogress": "^0.2.0", "ol": "^10.6.1", "pinia": "^3.0.3", @@ -64,9 +64,10 @@ "qs": "^6.14.0", "relation-graph": "^2.2.11", "screenfull": "^6.0.2", - "sm-crypto-v2": "^1.12.0", + "sm-crypto-v2": "^1.13.0", "sortablejs": "^1.15.6", "splitpanes": "^4.0.4", + "sql-formatter": "^15.6.6", "uuid": "^11.1.0", "vcrontab-3": "^3.3.22", "vform3-builds": "^3.0.10", @@ -74,47 +75,54 @@ "vue-clipboard3": "^2.0.0", "vue-demi": "0.14.10", "vue-draggable-plus": "^0.6.0", +<<<<<<< HEAD "vue-element-plus-x": "^1.3.11-beta", +======= + "vue-element-plus-x": "^1.3.0", +>>>>>>> 4030299f0e33e91ec524278c23382aadee7fbed3 "vue-grid-layout": "3.0.0-beta1", - "vue-i18n": "^11.1.5", - "vue-json-pretty": "^2.4.0", - "vue-markdown-shiki": "^2.0.0", + "vue-i18n": "^11.1.10", + "vue-json-pretty": "^2.5.0", "vue-plugin-hiprint": "^0.0.60", "vue-router": "^4.5.1", "vue-signature-pad": "^3.0.2", "vue3-tree-org": "^4.2.2", - "vxe-pc-ui": "^4.6.27", - "vxe-table": "^4.13.44", - "xe-utils": "^3.7.5", + "vxe-pc-ui": "^4.7.17", + "vxe-table": "^4.14.4", + "xe-utils": "^3.7.8", "xlsx-js-style": "^1.2.0" }, "devDependencies": { "@iconify/vue": "^5.0.0", "@plugin-web-update-notification/vite": "^2.0.0", "@types/lodash-es": "^4.17.12", - "@types/node": "^22.15.32", + "@types/node": "^22.15.35", "@types/nprogress": "^0.2.3", "@types/sortablejs": "^1.15.8", - "@typescript-eslint/eslint-plugin": "^8.34.1", - "@typescript-eslint/parser": "^8.34.1", - "@vitejs/plugin-vue": "^5.2.4", - "@vitejs/plugin-vue-jsx": "^4.2.0", + "@typescript-eslint/eslint-plugin": "^8.37.0", + "@typescript-eslint/parser": "^8.37.0", + "@vitejs/plugin-vue": "^6.0.0", + "@vitejs/plugin-vue-jsx": "^5.0.1", "@vue/compiler-sfc": "^3.5.17", - "code-inspector-plugin": "^0.20.12", - "eslint": "^9.29.0", - "eslint-plugin-vue": "^10.2.0", - "globals": "^16.2.0", - "less": "^4.3.0", - "prettier": "^3.5.3", + "code-inspector-plugin": "^0.20.17", + "eslint": "^9.31.0", + "eslint-plugin-vue": "^10.3.0", + "globals": "^16.3.0", + "less": "^4.4.0", + "prettier": "^3.6.2", "rollup-plugin-visualizer": "^6.0.3", "sass": "^1.89.2", "terser": "^5.43.1", "typescript": "^5.8.3", - "vite": "^6.3.5", + "vite": "^7.0.5", "vite-plugin-cdn-import": "^1.0.1", +<<<<<<< HEAD "vite-plugin-compression2": "^2.0.1", +======= + "vite-plugin-compression2": "^2.2.0", +>>>>>>> 4030299f0e33e91ec524278c23382aadee7fbed3 "vite-plugin-vue-setup-extend": "^0.4.0", - "vue-eslint-parser": "^10.1.3" + "vue-eslint-parser": "^10.2.0" }, "pnpm": { "onlyBuiltDependencies": [ @@ -129,7 +137,10 @@ "esbuild", "json-editor-vue", "vue-demi" - ] + ], + "overrides": { + "rollup": "4.43.0" + } }, "browserslist": [ "> 1%", diff --git a/Web/src/api-services/api.ts b/Web/src/api-services/api.ts index ec424ba0..5ae4203f 100644 --- a/Web/src/api-services/api.ts +++ b/Web/src/api-services/api.ts @@ -22,6 +22,7 @@ export * from './apis/sys-cache-api'; export * from './apis/sys-code-gen-api'; export * from './apis/sys-code-gen-config-api'; export * from './apis/sys-code-gen-template-api'; +export * from './apis/sys-column-custom-api'; export * from './apis/sys-common-api'; export * from './apis/sys-config-api'; export * from './apis/sys-config-tenant-api'; @@ -54,6 +55,9 @@ export * from './apis/sys-pos-api'; export * from './apis/sys-print-api'; export * from './apis/sys-proc-api'; export * from './apis/sys-region-api'; +export * from './apis/sys-report-config-api'; +export * from './apis/sys-report-data-source-api'; +export * from './apis/sys-report-group-api'; export * from './apis/sys-role-api'; export * from './apis/sys-schedule-api'; export * from './apis/sys-server-api'; diff --git a/Web/src/api-services/apis/sys-column-custom-api.ts b/Web/src/api-services/apis/sys-column-custom-api.ts new file mode 100644 index 00000000..3246b638 --- /dev/null +++ b/Web/src/api-services/apis/sys-column-custom-api.ts @@ -0,0 +1,310 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import globalAxios, { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios'; +import { Configuration } from '../configuration'; +// Some imports not used depending on template conditions +// @ts-ignore +import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base'; +import { AdminNETResultColumnCustomOutput } from '../models'; +import { ResetColumnCustomInput } from '../models'; +import { StoreColumnCustomInput } from '../models'; +/** + * SysColumnCustomApi - axios parameter creator + * @export + */ +export const SysColumnCustomApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary 获取用户表格列配置信息 🔖 + * @param {string} gridId 表格Id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysColumnCustomDetailGet: async (gridId: string, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'gridId' is not null or undefined + if (gridId === null || gridId === undefined) { + throw new RequiredError('gridId','Required parameter gridId was null or undefined when calling apiSysColumnCustomDetailGet.'); + } + const localVarPath = `/api/sysColumnCustom/detail`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + if (gridId !== undefined) { + localVarQueryParameter['GridId'] = gridId; + } + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 清除用户表格列配置信息 🔖 + * @param {ResetColumnCustomInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysColumnCustomResetPost: async (body?: ResetColumnCustomInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysColumnCustom/reset`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 保存用户表格列配置信息 🔖 + * @param {StoreColumnCustomInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysColumnCustomStorePost: async (body?: StoreColumnCustomInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysColumnCustom/store`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * SysColumnCustomApi - functional programming interface + * @export + */ +export const SysColumnCustomApiFp = function(configuration?: Configuration) { + return { + /** + * + * @summary 获取用户表格列配置信息 🔖 + * @param {string} gridId 表格Id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysColumnCustomDetailGet(gridId: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysColumnCustomApiAxiosParamCreator(configuration).apiSysColumnCustomDetailGet(gridId, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 清除用户表格列配置信息 🔖 + * @param {ResetColumnCustomInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysColumnCustomResetPost(body?: ResetColumnCustomInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysColumnCustomApiAxiosParamCreator(configuration).apiSysColumnCustomResetPost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 保存用户表格列配置信息 🔖 + * @param {StoreColumnCustomInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysColumnCustomStorePost(body?: StoreColumnCustomInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysColumnCustomApiAxiosParamCreator(configuration).apiSysColumnCustomStorePost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + } +}; + +/** + * SysColumnCustomApi - factory interface + * @export + */ +export const SysColumnCustomApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + return { + /** + * + * @summary 获取用户表格列配置信息 🔖 + * @param {string} gridId 表格Id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysColumnCustomDetailGet(gridId: string, options?: AxiosRequestConfig): Promise> { + return SysColumnCustomApiFp(configuration).apiSysColumnCustomDetailGet(gridId, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 清除用户表格列配置信息 🔖 + * @param {ResetColumnCustomInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysColumnCustomResetPost(body?: ResetColumnCustomInput, options?: AxiosRequestConfig): Promise> { + return SysColumnCustomApiFp(configuration).apiSysColumnCustomResetPost(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 保存用户表格列配置信息 🔖 + * @param {StoreColumnCustomInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysColumnCustomStorePost(body?: StoreColumnCustomInput, options?: AxiosRequestConfig): Promise> { + return SysColumnCustomApiFp(configuration).apiSysColumnCustomStorePost(body, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * SysColumnCustomApi - object-oriented interface + * @export + * @class SysColumnCustomApi + * @extends {BaseAPI} + */ +export class SysColumnCustomApi extends BaseAPI { + /** + * + * @summary 获取用户表格列配置信息 🔖 + * @param {string} gridId 表格Id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysColumnCustomApi + */ + public async apiSysColumnCustomDetailGet(gridId: string, options?: AxiosRequestConfig) : Promise> { + return SysColumnCustomApiFp(this.configuration).apiSysColumnCustomDetailGet(gridId, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 清除用户表格列配置信息 🔖 + * @param {ResetColumnCustomInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysColumnCustomApi + */ + public async apiSysColumnCustomResetPost(body?: ResetColumnCustomInput, options?: AxiosRequestConfig) : Promise> { + return SysColumnCustomApiFp(this.configuration).apiSysColumnCustomResetPost(body, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 保存用户表格列配置信息 🔖 + * @param {StoreColumnCustomInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysColumnCustomApi + */ + public async apiSysColumnCustomStorePost(body?: StoreColumnCustomInput, options?: AxiosRequestConfig) : Promise> { + return SysColumnCustomApiFp(this.configuration).apiSysColumnCustomStorePost(body, options).then((request) => request(this.axios, this.basePath)); + } +} diff --git a/Web/src/api-services/apis/sys-report-config-api.ts b/Web/src/api-services/apis/sys-report-config-api.ts new file mode 100644 index 00000000..ea1ddb6d --- /dev/null +++ b/Web/src/api-services/apis/sys-report-config-api.ts @@ -0,0 +1,816 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import globalAxios, { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios'; +import { Configuration } from '../configuration'; +// Some imports not used depending on template conditions +// @ts-ignore +import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base'; +import { AddReportConfigInput } from '../models'; +import { AdminNETResultFileStreamResult } from '../models'; +import { AdminNETResultListDictionaryStringObject } from '../models'; +import { AdminNETResultReportConfigParseSqlOutput } from '../models'; +import { AdminNETResultSqlSugarPagedListReportConfigOutput } from '../models'; +import { AdminNETResultSysReportLayoutConfig } from '../models'; +import { BaseIdInput } from '../models'; +import { PageReportConfigInput } from '../models'; +import { ReportConfigExecuteSqlScriptInput } from '../models'; +import { ReportConfigParseSqlInput } from '../models'; +import { UpdateReportConfigInput } from '../models'; +/** + * SysReportConfigApi - axios parameter creator + * @export + */ +export const SysReportConfigApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary 增加报表配置 + * @param {AddReportConfigInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportConfigAddPost: async (body?: AddReportConfigInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportConfig/add`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 复制报表配置 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportConfigCopyPost: async (body?: BaseIdInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportConfig/copy`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 删除报表配置 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportConfigDeletePost: async (body?: BaseIdInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportConfig/delete`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 执行报表配置Sql脚本 + * @param {ReportConfigExecuteSqlScriptInput} [body] 输入参数 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportConfigExecuteSqlScriptPost: async (body?: ReportConfigExecuteSqlScriptInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportConfig/executeSqlScript`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 导出报表到Excel + * @param {ReportConfigExecuteSqlScriptInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportConfigExportToExcelPost: async (body?: ReportConfigExecuteSqlScriptInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportConfig/exportToExcel`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 获取报表布局配置 + * @param {number} id 主键Id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportConfigGetLayoutConfigGet: async (id: number, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'id' is not null or undefined + if (id === null || id === undefined) { + throw new RequiredError('id','Required parameter id was null or undefined when calling apiSysReportConfigGetLayoutConfigGet.'); + } + const localVarPath = `/api/sysReportConfig/getLayoutConfig`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + if (id !== undefined) { + localVarQueryParameter['Id'] = id; + } + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 获取报表配置分页列表 + * @param {PageReportConfigInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportConfigPagePost: async (body?: PageReportConfigInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportConfig/page`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 解析报表配置Sql + * @param {ReportConfigParseSqlInput} [body] 输入参数 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportConfigParseSqlPost: async (body?: ReportConfigParseSqlInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportConfig/parseSql`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 更新报表配置 + * @param {UpdateReportConfigInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportConfigUpdatePost: async (body?: UpdateReportConfigInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportConfig/update`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * SysReportConfigApi - functional programming interface + * @export + */ +export const SysReportConfigApiFp = function(configuration?: Configuration) { + return { + /** + * + * @summary 增加报表配置 + * @param {AddReportConfigInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigAddPost(body?: AddReportConfigInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportConfigApiAxiosParamCreator(configuration).apiSysReportConfigAddPost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 复制报表配置 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigCopyPost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportConfigApiAxiosParamCreator(configuration).apiSysReportConfigCopyPost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 删除报表配置 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportConfigApiAxiosParamCreator(configuration).apiSysReportConfigDeletePost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 执行报表配置Sql脚本 + * @param {ReportConfigExecuteSqlScriptInput} [body] 输入参数 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigExecuteSqlScriptPost(body?: ReportConfigExecuteSqlScriptInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportConfigApiAxiosParamCreator(configuration).apiSysReportConfigExecuteSqlScriptPost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 导出报表到Excel + * @param {ReportConfigExecuteSqlScriptInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigExportToExcelPost(body?: ReportConfigExecuteSqlScriptInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportConfigApiAxiosParamCreator(configuration).apiSysReportConfigExportToExcelPost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 获取报表布局配置 + * @param {number} id 主键Id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigGetLayoutConfigGet(id: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportConfigApiAxiosParamCreator(configuration).apiSysReportConfigGetLayoutConfigGet(id, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 获取报表配置分页列表 + * @param {PageReportConfigInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigPagePost(body?: PageReportConfigInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportConfigApiAxiosParamCreator(configuration).apiSysReportConfigPagePost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 解析报表配置Sql + * @param {ReportConfigParseSqlInput} [body] 输入参数 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigParseSqlPost(body?: ReportConfigParseSqlInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportConfigApiAxiosParamCreator(configuration).apiSysReportConfigParseSqlPost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 更新报表配置 + * @param {UpdateReportConfigInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigUpdatePost(body?: UpdateReportConfigInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportConfigApiAxiosParamCreator(configuration).apiSysReportConfigUpdatePost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + } +}; + +/** + * SysReportConfigApi - factory interface + * @export + */ +export const SysReportConfigApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + return { + /** + * + * @summary 增加报表配置 + * @param {AddReportConfigInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigAddPost(body?: AddReportConfigInput, options?: AxiosRequestConfig): Promise> { + return SysReportConfigApiFp(configuration).apiSysReportConfigAddPost(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 复制报表配置 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigCopyPost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise> { + return SysReportConfigApiFp(configuration).apiSysReportConfigCopyPost(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 删除报表配置 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise> { + return SysReportConfigApiFp(configuration).apiSysReportConfigDeletePost(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 执行报表配置Sql脚本 + * @param {ReportConfigExecuteSqlScriptInput} [body] 输入参数 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigExecuteSqlScriptPost(body?: ReportConfigExecuteSqlScriptInput, options?: AxiosRequestConfig): Promise> { + return SysReportConfigApiFp(configuration).apiSysReportConfigExecuteSqlScriptPost(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 导出报表到Excel + * @param {ReportConfigExecuteSqlScriptInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigExportToExcelPost(body?: ReportConfigExecuteSqlScriptInput, options?: AxiosRequestConfig): Promise> { + return SysReportConfigApiFp(configuration).apiSysReportConfigExportToExcelPost(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 获取报表布局配置 + * @param {number} id 主键Id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigGetLayoutConfigGet(id: number, options?: AxiosRequestConfig): Promise> { + return SysReportConfigApiFp(configuration).apiSysReportConfigGetLayoutConfigGet(id, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 获取报表配置分页列表 + * @param {PageReportConfigInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigPagePost(body?: PageReportConfigInput, options?: AxiosRequestConfig): Promise> { + return SysReportConfigApiFp(configuration).apiSysReportConfigPagePost(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 解析报表配置Sql + * @param {ReportConfigParseSqlInput} [body] 输入参数 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigParseSqlPost(body?: ReportConfigParseSqlInput, options?: AxiosRequestConfig): Promise> { + return SysReportConfigApiFp(configuration).apiSysReportConfigParseSqlPost(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 更新报表配置 + * @param {UpdateReportConfigInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportConfigUpdatePost(body?: UpdateReportConfigInput, options?: AxiosRequestConfig): Promise> { + return SysReportConfigApiFp(configuration).apiSysReportConfigUpdatePost(body, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * SysReportConfigApi - object-oriented interface + * @export + * @class SysReportConfigApi + * @extends {BaseAPI} + */ +export class SysReportConfigApi extends BaseAPI { + /** + * + * @summary 增加报表配置 + * @param {AddReportConfigInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportConfigApi + */ + public async apiSysReportConfigAddPost(body?: AddReportConfigInput, options?: AxiosRequestConfig) : Promise> { + return SysReportConfigApiFp(this.configuration).apiSysReportConfigAddPost(body, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 复制报表配置 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportConfigApi + */ + public async apiSysReportConfigCopyPost(body?: BaseIdInput, options?: AxiosRequestConfig) : Promise> { + return SysReportConfigApiFp(this.configuration).apiSysReportConfigCopyPost(body, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 删除报表配置 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportConfigApi + */ + public async apiSysReportConfigDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig) : Promise> { + return SysReportConfigApiFp(this.configuration).apiSysReportConfigDeletePost(body, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 执行报表配置Sql脚本 + * @param {ReportConfigExecuteSqlScriptInput} [body] 输入参数 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportConfigApi + */ + public async apiSysReportConfigExecuteSqlScriptPost(body?: ReportConfigExecuteSqlScriptInput, options?: AxiosRequestConfig) : Promise> { + return SysReportConfigApiFp(this.configuration).apiSysReportConfigExecuteSqlScriptPost(body, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 导出报表到Excel + * @param {ReportConfigExecuteSqlScriptInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportConfigApi + */ + public async apiSysReportConfigExportToExcelPost(body?: ReportConfigExecuteSqlScriptInput, options?: AxiosRequestConfig) : Promise> { + return SysReportConfigApiFp(this.configuration).apiSysReportConfigExportToExcelPost(body, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 获取报表布局配置 + * @param {number} id 主键Id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportConfigApi + */ + public async apiSysReportConfigGetLayoutConfigGet(id: number, options?: AxiosRequestConfig) : Promise> { + return SysReportConfigApiFp(this.configuration).apiSysReportConfigGetLayoutConfigGet(id, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 获取报表配置分页列表 + * @param {PageReportConfigInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportConfigApi + */ + public async apiSysReportConfigPagePost(body?: PageReportConfigInput, options?: AxiosRequestConfig) : Promise> { + return SysReportConfigApiFp(this.configuration).apiSysReportConfigPagePost(body, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 解析报表配置Sql + * @param {ReportConfigParseSqlInput} [body] 输入参数 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportConfigApi + */ + public async apiSysReportConfigParseSqlPost(body?: ReportConfigParseSqlInput, options?: AxiosRequestConfig) : Promise> { + return SysReportConfigApiFp(this.configuration).apiSysReportConfigParseSqlPost(body, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 更新报表配置 + * @param {UpdateReportConfigInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportConfigApi + */ + public async apiSysReportConfigUpdatePost(body?: UpdateReportConfigInput, options?: AxiosRequestConfig) : Promise> { + return SysReportConfigApiFp(this.configuration).apiSysReportConfigUpdatePost(body, options).then((request) => request(this.axios, this.basePath)); + } +} diff --git a/Web/src/api-services/apis/sys-report-data-source-api.ts b/Web/src/api-services/apis/sys-report-data-source-api.ts new file mode 100644 index 00000000..713a2247 --- /dev/null +++ b/Web/src/api-services/apis/sys-report-data-source-api.ts @@ -0,0 +1,467 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import globalAxios, { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios'; +import { Configuration } from '../configuration'; +// Some imports not used depending on template conditions +// @ts-ignore +import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base'; +import { AddReportDataSourceInput } from '../models'; +import { AdminNETResultListReportDataSourceOutput } from '../models'; +import { AdminNETResultSqlSugarPagedListSysReportDataSource } from '../models'; +import { BaseIdInput } from '../models'; +import { PageReportDataSourceInput } from '../models'; +import { UpdateReportDataSourceInput } from '../models'; +/** + * SysReportDataSourceApi - axios parameter creator + * @export + */ +export const SysReportDataSourceApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary 增加报表数据源 + * @param {AddReportDataSourceInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportDataSourceAddPost: async (body?: AddReportDataSourceInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportDataSource/add`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 获取报表数据源列表 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportDataSourceDataSourceListGet: async (options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportDataSource/dataSourceList`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 删除报表数据源 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportDataSourceDeletePost: async (body?: BaseIdInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportDataSource/delete`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 获取报表数据源分页列表 + * @param {PageReportDataSourceInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportDataSourcePagePost: async (body?: PageReportDataSourceInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportDataSource/page`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 更新报表数据源 + * @param {UpdateReportDataSourceInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportDataSourceUpdatePost: async (body?: UpdateReportDataSourceInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportDataSource/update`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * SysReportDataSourceApi - functional programming interface + * @export + */ +export const SysReportDataSourceApiFp = function(configuration?: Configuration) { + return { + /** + * + * @summary 增加报表数据源 + * @param {AddReportDataSourceInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportDataSourceAddPost(body?: AddReportDataSourceInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportDataSourceApiAxiosParamCreator(configuration).apiSysReportDataSourceAddPost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 获取报表数据源列表 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportDataSourceDataSourceListGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportDataSourceApiAxiosParamCreator(configuration).apiSysReportDataSourceDataSourceListGet(options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 删除报表数据源 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportDataSourceDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportDataSourceApiAxiosParamCreator(configuration).apiSysReportDataSourceDeletePost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 获取报表数据源分页列表 + * @param {PageReportDataSourceInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportDataSourcePagePost(body?: PageReportDataSourceInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportDataSourceApiAxiosParamCreator(configuration).apiSysReportDataSourcePagePost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 更新报表数据源 + * @param {UpdateReportDataSourceInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportDataSourceUpdatePost(body?: UpdateReportDataSourceInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportDataSourceApiAxiosParamCreator(configuration).apiSysReportDataSourceUpdatePost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + } +}; + +/** + * SysReportDataSourceApi - factory interface + * @export + */ +export const SysReportDataSourceApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + return { + /** + * + * @summary 增加报表数据源 + * @param {AddReportDataSourceInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportDataSourceAddPost(body?: AddReportDataSourceInput, options?: AxiosRequestConfig): Promise> { + return SysReportDataSourceApiFp(configuration).apiSysReportDataSourceAddPost(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 获取报表数据源列表 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportDataSourceDataSourceListGet(options?: AxiosRequestConfig): Promise> { + return SysReportDataSourceApiFp(configuration).apiSysReportDataSourceDataSourceListGet(options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 删除报表数据源 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportDataSourceDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise> { + return SysReportDataSourceApiFp(configuration).apiSysReportDataSourceDeletePost(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 获取报表数据源分页列表 + * @param {PageReportDataSourceInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportDataSourcePagePost(body?: PageReportDataSourceInput, options?: AxiosRequestConfig): Promise> { + return SysReportDataSourceApiFp(configuration).apiSysReportDataSourcePagePost(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 更新报表数据源 + * @param {UpdateReportDataSourceInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportDataSourceUpdatePost(body?: UpdateReportDataSourceInput, options?: AxiosRequestConfig): Promise> { + return SysReportDataSourceApiFp(configuration).apiSysReportDataSourceUpdatePost(body, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * SysReportDataSourceApi - object-oriented interface + * @export + * @class SysReportDataSourceApi + * @extends {BaseAPI} + */ +export class SysReportDataSourceApi extends BaseAPI { + /** + * + * @summary 增加报表数据源 + * @param {AddReportDataSourceInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportDataSourceApi + */ + public async apiSysReportDataSourceAddPost(body?: AddReportDataSourceInput, options?: AxiosRequestConfig) : Promise> { + return SysReportDataSourceApiFp(this.configuration).apiSysReportDataSourceAddPost(body, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 获取报表数据源列表 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportDataSourceApi + */ + public async apiSysReportDataSourceDataSourceListGet(options?: AxiosRequestConfig) : Promise> { + return SysReportDataSourceApiFp(this.configuration).apiSysReportDataSourceDataSourceListGet(options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 删除报表数据源 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportDataSourceApi + */ + public async apiSysReportDataSourceDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig) : Promise> { + return SysReportDataSourceApiFp(this.configuration).apiSysReportDataSourceDeletePost(body, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 获取报表数据源分页列表 + * @param {PageReportDataSourceInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportDataSourceApi + */ + public async apiSysReportDataSourcePagePost(body?: PageReportDataSourceInput, options?: AxiosRequestConfig) : Promise> { + return SysReportDataSourceApiFp(this.configuration).apiSysReportDataSourcePagePost(body, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 更新报表数据源 + * @param {UpdateReportDataSourceInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportDataSourceApi + */ + public async apiSysReportDataSourceUpdatePost(body?: UpdateReportDataSourceInput, options?: AxiosRequestConfig) : Promise> { + return SysReportDataSourceApiFp(this.configuration).apiSysReportDataSourceUpdatePost(body, options).then((request) => request(this.axios, this.basePath)); + } +} diff --git a/Web/src/api-services/apis/sys-report-group-api.ts b/Web/src/api-services/apis/sys-report-group-api.ts new file mode 100644 index 00000000..1a216833 --- /dev/null +++ b/Web/src/api-services/apis/sys-report-group-api.ts @@ -0,0 +1,382 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import globalAxios, { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios'; +import { Configuration } from '../configuration'; +// Some imports not used depending on template conditions +// @ts-ignore +import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base'; +import { AddReportGroupInput } from '../models'; +import { AdminNETResultListSysReportGroup } from '../models'; +import { BaseIdInput } from '../models'; +import { UpdateReportGroupInput } from '../models'; +/** + * SysReportGroupApi - axios parameter creator + * @export + */ +export const SysReportGroupApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary 增加报表分组 + * @param {AddReportGroupInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportGroupAddPost: async (body?: AddReportGroupInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportGroup/add`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 删除报表分组 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportGroupDeletePost: async (body?: BaseIdInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportGroup/delete`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 获取报表分组列表 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportGroupListGet: async (options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportGroup/list`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 更新报表分组 + * @param {UpdateReportGroupInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysReportGroupUpdatePost: async (body?: UpdateReportGroupInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysReportGroup/update`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * SysReportGroupApi - functional programming interface + * @export + */ +export const SysReportGroupApiFp = function(configuration?: Configuration) { + return { + /** + * + * @summary 增加报表分组 + * @param {AddReportGroupInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportGroupAddPost(body?: AddReportGroupInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportGroupApiAxiosParamCreator(configuration).apiSysReportGroupAddPost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 删除报表分组 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportGroupDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportGroupApiAxiosParamCreator(configuration).apiSysReportGroupDeletePost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 获取报表分组列表 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportGroupListGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportGroupApiAxiosParamCreator(configuration).apiSysReportGroupListGet(options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary 更新报表分组 + * @param {UpdateReportGroupInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportGroupUpdatePost(body?: UpdateReportGroupInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysReportGroupApiAxiosParamCreator(configuration).apiSysReportGroupUpdatePost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + } +}; + +/** + * SysReportGroupApi - factory interface + * @export + */ +export const SysReportGroupApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + return { + /** + * + * @summary 增加报表分组 + * @param {AddReportGroupInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportGroupAddPost(body?: AddReportGroupInput, options?: AxiosRequestConfig): Promise> { + return SysReportGroupApiFp(configuration).apiSysReportGroupAddPost(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 删除报表分组 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportGroupDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise> { + return SysReportGroupApiFp(configuration).apiSysReportGroupDeletePost(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 获取报表分组列表 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportGroupListGet(options?: AxiosRequestConfig): Promise> { + return SysReportGroupApiFp(configuration).apiSysReportGroupListGet(options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary 更新报表分组 + * @param {UpdateReportGroupInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysReportGroupUpdatePost(body?: UpdateReportGroupInput, options?: AxiosRequestConfig): Promise> { + return SysReportGroupApiFp(configuration).apiSysReportGroupUpdatePost(body, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * SysReportGroupApi - object-oriented interface + * @export + * @class SysReportGroupApi + * @extends {BaseAPI} + */ +export class SysReportGroupApi extends BaseAPI { + /** + * + * @summary 增加报表分组 + * @param {AddReportGroupInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportGroupApi + */ + public async apiSysReportGroupAddPost(body?: AddReportGroupInput, options?: AxiosRequestConfig) : Promise> { + return SysReportGroupApiFp(this.configuration).apiSysReportGroupAddPost(body, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 删除报表分组 + * @param {BaseIdInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportGroupApi + */ + public async apiSysReportGroupDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig) : Promise> { + return SysReportGroupApiFp(this.configuration).apiSysReportGroupDeletePost(body, options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 获取报表分组列表 + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportGroupApi + */ + public async apiSysReportGroupListGet(options?: AxiosRequestConfig) : Promise> { + return SysReportGroupApiFp(this.configuration).apiSysReportGroupListGet(options).then((request) => request(this.axios, this.basePath)); + } + /** + * + * @summary 更新报表分组 + * @param {UpdateReportGroupInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysReportGroupApi + */ + public async apiSysReportGroupUpdatePost(body?: UpdateReportGroupInput, options?: AxiosRequestConfig) : Promise> { + return SysReportGroupApiFp(this.configuration).apiSysReportGroupUpdatePost(body, options).then((request) => request(this.axios, this.basePath)); + } +} diff --git a/Web/src/api-services/models/add-report-config-input.ts b/Web/src/api-services/models/add-report-config-input.ts new file mode 100644 index 00000000..29ac1f63 --- /dev/null +++ b/Web/src/api-services/models/add-report-config-input.ts @@ -0,0 +1,180 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { ReportConfigDsTypeEnum } from './report-config-ds-type-enum'; +import { SysReportGroup } from './sys-report-group'; + /** + * + * + * @export + * @interface AddReportConfigInput + */ +export interface AddReportConfigInput { + + /** + * 雪花Id + * + * @type {number} + * @memberof AddReportConfigInput + */ + id?: number; + + /** + * 创建时间 + * + * @type {Date} + * @memberof AddReportConfigInput + */ + createTime?: Date; + + /** + * 更新时间 + * + * @type {Date} + * @memberof AddReportConfigInput + */ + updateTime?: Date | null; + + /** + * 创建者Id + * + * @type {number} + * @memberof AddReportConfigInput + */ + createUserId?: number | null; + + /** + * 创建者姓名 + * + * @type {string} + * @memberof AddReportConfigInput + */ + createUserName?: string | null; + + /** + * 修改者Id + * + * @type {number} + * @memberof AddReportConfigInput + */ + updateUserId?: number | null; + + /** + * 修改者姓名 + * + * @type {string} + * @memberof AddReportConfigInput + */ + updateUserName?: string | null; + + /** + * 软删除 + * + * @type {boolean} + * @memberof AddReportConfigInput + */ + isDelete?: boolean; + + /** + * 名称 + * + * @type {string} + * @memberof AddReportConfigInput + */ + name?: string | null; + + /** + * 描述 + * + * @type {string} + * @memberof AddReportConfigInput + */ + description?: string | null; + + /** + * @type {ReportConfigDsTypeEnum} + * @memberof AddReportConfigInput + */ + dsType?: ReportConfigDsTypeEnum; + + /** + * 数据源 + * + * @type {string} + * @memberof AddReportConfigInput + */ + dataSource?: string | null; + + /** + * 分组Id + * + * @type {number} + * @memberof AddReportConfigInput + */ + groupId?: number | null; + + /** + * @type {SysReportGroup} + * @memberof AddReportConfigInput + */ + group?: SysReportGroup; + + /** + * 脚本语句 + * + * @type {string} + * @memberof AddReportConfigInput + */ + sqlScript?: string | null; + + /** + * 接口地址 + * + * @type {string} + * @memberof AddReportConfigInput + */ + apiUrl?: string | null; + + /** + * 接口请求方式 + * + * @type {string} + * @memberof AddReportConfigInput + */ + apiHttpMethod?: string | null; + + /** + * 接口参数 + * + * @type {string} + * @memberof AddReportConfigInput + */ + apiParams?: string | null; + + /** + * 参数 + * + * @type {string} + * @memberof AddReportConfigInput + */ + params?: string | null; + + /** + * 列表字段 + * + * @type {string} + * @memberof AddReportConfigInput + */ + fields?: string | null; +} diff --git a/Web/src/api-services/models/add-report-data-source-input.ts b/Web/src/api-services/models/add-report-data-source-input.ts new file mode 100644 index 00000000..944ed925 --- /dev/null +++ b/Web/src/api-services/models/add-report-data-source-input.ts @@ -0,0 +1,118 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * + * + * @export + * @interface AddReportDataSourceInput + */ +export interface AddReportDataSourceInput { + + /** + * 雪花Id + * + * @type {number} + * @memberof AddReportDataSourceInput + */ + id?: number; + + /** + * 创建时间 + * + * @type {Date} + * @memberof AddReportDataSourceInput + */ + createTime?: Date; + + /** + * 更新时间 + * + * @type {Date} + * @memberof AddReportDataSourceInput + */ + updateTime?: Date | null; + + /** + * 创建者Id + * + * @type {number} + * @memberof AddReportDataSourceInput + */ + createUserId?: number | null; + + /** + * 创建者姓名 + * + * @type {string} + * @memberof AddReportDataSourceInput + */ + createUserName?: string | null; + + /** + * 修改者Id + * + * @type {number} + * @memberof AddReportDataSourceInput + */ + updateUserId?: number | null; + + /** + * 修改者姓名 + * + * @type {string} + * @memberof AddReportDataSourceInput + */ + updateUserName?: string | null; + + /** + * 软删除 + * + * @type {boolean} + * @memberof AddReportDataSourceInput + */ + isDelete?: boolean; + + /** + * 名称 + * + * @type {string} + * @memberof AddReportDataSourceInput + */ + name?: string | null; + + /** + * 数据库类型 + * + * @type {string} + * @memberof AddReportDataSourceInput + */ + dbType?: string | null; + + /** + * 连接字符串 + * + * @type {string} + * @memberof AddReportDataSourceInput + */ + connectionString?: string | null; + + /** + * 备注 + * + * @type {string} + * @memberof AddReportDataSourceInput + */ + remark?: string | null; +} diff --git a/Web/src/api-services/models/add-report-group-input.ts b/Web/src/api-services/models/add-report-group-input.ts new file mode 100644 index 00000000..04da9e7a --- /dev/null +++ b/Web/src/api-services/models/add-report-group-input.ts @@ -0,0 +1,102 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * + * + * @export + * @interface AddReportGroupInput + */ +export interface AddReportGroupInput { + + /** + * 雪花Id + * + * @type {number} + * @memberof AddReportGroupInput + */ + id?: number; + + /** + * 创建时间 + * + * @type {Date} + * @memberof AddReportGroupInput + */ + createTime?: Date; + + /** + * 更新时间 + * + * @type {Date} + * @memberof AddReportGroupInput + */ + updateTime?: Date | null; + + /** + * 创建者Id + * + * @type {number} + * @memberof AddReportGroupInput + */ + createUserId?: number | null; + + /** + * 创建者姓名 + * + * @type {string} + * @memberof AddReportGroupInput + */ + createUserName?: string | null; + + /** + * 修改者Id + * + * @type {number} + * @memberof AddReportGroupInput + */ + updateUserId?: number | null; + + /** + * 修改者姓名 + * + * @type {string} + * @memberof AddReportGroupInput + */ + updateUserName?: string | null; + + /** + * 软删除 + * + * @type {boolean} + * @memberof AddReportGroupInput + */ + isDelete?: boolean; + + /** + * 编码 + * + * @type {string} + * @memberof AddReportGroupInput + */ + number?: string | null; + + /** + * 名称 + * + * @type {string} + * @memberof AddReportGroupInput + */ + name?: string | null; +} diff --git a/Web/src/api-services/models/admin-netresult-column-custom-output.ts b/Web/src/api-services/models/admin-netresult-column-custom-output.ts new file mode 100644 index 00000000..fd5163b6 --- /dev/null +++ b/Web/src/api-services/models/admin-netresult-column-custom-output.ts @@ -0,0 +1,69 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { ColumnCustomOutput } from './column-custom-output'; + /** + * 全局返回结果 + * + * @export + * @interface AdminNETResultColumnCustomOutput + */ +export interface AdminNETResultColumnCustomOutput { + + /** + * 状态码 + * + * @type {number} + * @memberof AdminNETResultColumnCustomOutput + */ + code?: number; + + /** + * 类型success、warning、error + * + * @type {string} + * @memberof AdminNETResultColumnCustomOutput + */ + type?: string | null; + + /** + * 错误信息 + * + * @type {string} + * @memberof AdminNETResultColumnCustomOutput + */ + message?: string | null; + + /** + * @type {ColumnCustomOutput} + * @memberof AdminNETResultColumnCustomOutput + */ + result?: ColumnCustomOutput; + + /** + * 附加数据 + * + * @type {any} + * @memberof AdminNETResultColumnCustomOutput + */ + extras?: any | null; + + /** + * 时间 + * + * @type {Date} + * @memberof AdminNETResultColumnCustomOutput + */ + time?: Date; +} diff --git a/Web/src/api-services/models/admin-netresult-file-stream-result.ts b/Web/src/api-services/models/admin-netresult-file-stream-result.ts new file mode 100644 index 00000000..43217183 --- /dev/null +++ b/Web/src/api-services/models/admin-netresult-file-stream-result.ts @@ -0,0 +1,70 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 全局返回结果 + * + * @export + * @interface AdminNETResultFileStreamResult + */ +export interface AdminNETResultFileStreamResult { + + /** + * 状态码 + * + * @type {number} + * @memberof AdminNETResultFileStreamResult + */ + code?: number; + + /** + * 类型success、warning、error + * + * @type {string} + * @memberof AdminNETResultFileStreamResult + */ + type?: string | null; + + /** + * 错误信息 + * + * @type {string} + * @memberof AdminNETResultFileStreamResult + */ + message?: string | null; + + /** + * 数据 + * + * @type {Blob} + * @memberof AdminNETResultFileStreamResult + */ + result?: Blob | null; + + /** + * 附加数据 + * + * @type {any} + * @memberof AdminNETResultFileStreamResult + */ + extras?: any | null; + + /** + * 时间 + * + * @type {Date} + * @memberof AdminNETResultFileStreamResult + */ + time?: Date; +} diff --git a/Web/src/api-services/models/admin-netresult-list-dictionary-string-object.ts b/Web/src/api-services/models/admin-netresult-list-dictionary-string-object.ts new file mode 100644 index 00000000..9ecee875 --- /dev/null +++ b/Web/src/api-services/models/admin-netresult-list-dictionary-string-object.ts @@ -0,0 +1,70 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 全局返回结果 + * + * @export + * @interface AdminNETResultListDictionaryStringObject + */ +export interface AdminNETResultListDictionaryStringObject { + + /** + * 状态码 + * + * @type {number} + * @memberof AdminNETResultListDictionaryStringObject + */ + code?: number; + + /** + * 类型success、warning、error + * + * @type {string} + * @memberof AdminNETResultListDictionaryStringObject + */ + type?: string | null; + + /** + * 错误信息 + * + * @type {string} + * @memberof AdminNETResultListDictionaryStringObject + */ + message?: string | null; + + /** + * 数据 + * + * @type {Array<{ [key: string]: any; }>} + * @memberof AdminNETResultListDictionaryStringObject + */ + result?: Array<{ [key: string]: any; }> | null; + + /** + * 附加数据 + * + * @type {any} + * @memberof AdminNETResultListDictionaryStringObject + */ + extras?: any | null; + + /** + * 时间 + * + * @type {Date} + * @memberof AdminNETResultListDictionaryStringObject + */ + time?: Date; +} diff --git a/Web/src/api-services/models/admin-netresult-list-report-data-source-output.ts b/Web/src/api-services/models/admin-netresult-list-report-data-source-output.ts new file mode 100644 index 00000000..f6d52307 --- /dev/null +++ b/Web/src/api-services/models/admin-netresult-list-report-data-source-output.ts @@ -0,0 +1,71 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { ReportDataSourceOutput } from './report-data-source-output'; + /** + * 全局返回结果 + * + * @export + * @interface AdminNETResultListReportDataSourceOutput + */ +export interface AdminNETResultListReportDataSourceOutput { + + /** + * 状态码 + * + * @type {number} + * @memberof AdminNETResultListReportDataSourceOutput + */ + code?: number; + + /** + * 类型success、warning、error + * + * @type {string} + * @memberof AdminNETResultListReportDataSourceOutput + */ + type?: string | null; + + /** + * 错误信息 + * + * @type {string} + * @memberof AdminNETResultListReportDataSourceOutput + */ + message?: string | null; + + /** + * 数据 + * + * @type {Array} + * @memberof AdminNETResultListReportDataSourceOutput + */ + result?: Array | null; + + /** + * 附加数据 + * + * @type {any} + * @memberof AdminNETResultListReportDataSourceOutput + */ + extras?: any | null; + + /** + * 时间 + * + * @type {Date} + * @memberof AdminNETResultListReportDataSourceOutput + */ + time?: Date; +} diff --git a/Web/src/api-services/models/admin-netresult-list-sys-report-group.ts b/Web/src/api-services/models/admin-netresult-list-sys-report-group.ts new file mode 100644 index 00000000..28c7d856 --- /dev/null +++ b/Web/src/api-services/models/admin-netresult-list-sys-report-group.ts @@ -0,0 +1,71 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { SysReportGroup } from './sys-report-group'; + /** + * 全局返回结果 + * + * @export + * @interface AdminNETResultListSysReportGroup + */ +export interface AdminNETResultListSysReportGroup { + + /** + * 状态码 + * + * @type {number} + * @memberof AdminNETResultListSysReportGroup + */ + code?: number; + + /** + * 类型success、warning、error + * + * @type {string} + * @memberof AdminNETResultListSysReportGroup + */ + type?: string | null; + + /** + * 错误信息 + * + * @type {string} + * @memberof AdminNETResultListSysReportGroup + */ + message?: string | null; + + /** + * 数据 + * + * @type {Array} + * @memberof AdminNETResultListSysReportGroup + */ + result?: Array | null; + + /** + * 附加数据 + * + * @type {any} + * @memberof AdminNETResultListSysReportGroup + */ + extras?: any | null; + + /** + * 时间 + * + * @type {Date} + * @memberof AdminNETResultListSysReportGroup + */ + time?: Date; +} diff --git a/Web/src/api-services/models/admin-netresult-report-config-parse-sql-output.ts b/Web/src/api-services/models/admin-netresult-report-config-parse-sql-output.ts new file mode 100644 index 00000000..7b0361d8 --- /dev/null +++ b/Web/src/api-services/models/admin-netresult-report-config-parse-sql-output.ts @@ -0,0 +1,69 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { ReportConfigParseSqlOutput } from './report-config-parse-sql-output'; + /** + * 全局返回结果 + * + * @export + * @interface AdminNETResultReportConfigParseSqlOutput + */ +export interface AdminNETResultReportConfigParseSqlOutput { + + /** + * 状态码 + * + * @type {number} + * @memberof AdminNETResultReportConfigParseSqlOutput + */ + code?: number; + + /** + * 类型success、warning、error + * + * @type {string} + * @memberof AdminNETResultReportConfigParseSqlOutput + */ + type?: string | null; + + /** + * 错误信息 + * + * @type {string} + * @memberof AdminNETResultReportConfigParseSqlOutput + */ + message?: string | null; + + /** + * @type {ReportConfigParseSqlOutput} + * @memberof AdminNETResultReportConfigParseSqlOutput + */ + result?: ReportConfigParseSqlOutput; + + /** + * 附加数据 + * + * @type {any} + * @memberof AdminNETResultReportConfigParseSqlOutput + */ + extras?: any | null; + + /** + * 时间 + * + * @type {Date} + * @memberof AdminNETResultReportConfigParseSqlOutput + */ + time?: Date; +} diff --git a/Web/src/api-services/models/admin-netresult-sql-sugar-paged-list-report-config-output.ts b/Web/src/api-services/models/admin-netresult-sql-sugar-paged-list-report-config-output.ts new file mode 100644 index 00000000..6282b392 --- /dev/null +++ b/Web/src/api-services/models/admin-netresult-sql-sugar-paged-list-report-config-output.ts @@ -0,0 +1,69 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { SqlSugarPagedListReportConfigOutput } from './sql-sugar-paged-list-report-config-output'; + /** + * 全局返回结果 + * + * @export + * @interface AdminNETResultSqlSugarPagedListReportConfigOutput + */ +export interface AdminNETResultSqlSugarPagedListReportConfigOutput { + + /** + * 状态码 + * + * @type {number} + * @memberof AdminNETResultSqlSugarPagedListReportConfigOutput + */ + code?: number; + + /** + * 类型success、warning、error + * + * @type {string} + * @memberof AdminNETResultSqlSugarPagedListReportConfigOutput + */ + type?: string | null; + + /** + * 错误信息 + * + * @type {string} + * @memberof AdminNETResultSqlSugarPagedListReportConfigOutput + */ + message?: string | null; + + /** + * @type {SqlSugarPagedListReportConfigOutput} + * @memberof AdminNETResultSqlSugarPagedListReportConfigOutput + */ + result?: SqlSugarPagedListReportConfigOutput; + + /** + * 附加数据 + * + * @type {any} + * @memberof AdminNETResultSqlSugarPagedListReportConfigOutput + */ + extras?: any | null; + + /** + * 时间 + * + * @type {Date} + * @memberof AdminNETResultSqlSugarPagedListReportConfigOutput + */ + time?: Date; +} diff --git a/Web/src/api-services/models/admin-netresult-sql-sugar-paged-list-sys-report-data-source.ts b/Web/src/api-services/models/admin-netresult-sql-sugar-paged-list-sys-report-data-source.ts new file mode 100644 index 00000000..563b8df8 --- /dev/null +++ b/Web/src/api-services/models/admin-netresult-sql-sugar-paged-list-sys-report-data-source.ts @@ -0,0 +1,69 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { SqlSugarPagedListSysReportDataSource } from './sql-sugar-paged-list-sys-report-data-source'; + /** + * 全局返回结果 + * + * @export + * @interface AdminNETResultSqlSugarPagedListSysReportDataSource + */ +export interface AdminNETResultSqlSugarPagedListSysReportDataSource { + + /** + * 状态码 + * + * @type {number} + * @memberof AdminNETResultSqlSugarPagedListSysReportDataSource + */ + code?: number; + + /** + * 类型success、warning、error + * + * @type {string} + * @memberof AdminNETResultSqlSugarPagedListSysReportDataSource + */ + type?: string | null; + + /** + * 错误信息 + * + * @type {string} + * @memberof AdminNETResultSqlSugarPagedListSysReportDataSource + */ + message?: string | null; + + /** + * @type {SqlSugarPagedListSysReportDataSource} + * @memberof AdminNETResultSqlSugarPagedListSysReportDataSource + */ + result?: SqlSugarPagedListSysReportDataSource; + + /** + * 附加数据 + * + * @type {any} + * @memberof AdminNETResultSqlSugarPagedListSysReportDataSource + */ + extras?: any | null; + + /** + * 时间 + * + * @type {Date} + * @memberof AdminNETResultSqlSugarPagedListSysReportDataSource + */ + time?: Date; +} diff --git a/Web/src/api-services/models/admin-netresult-sys-report-layout-config.ts b/Web/src/api-services/models/admin-netresult-sys-report-layout-config.ts new file mode 100644 index 00000000..c68ee974 --- /dev/null +++ b/Web/src/api-services/models/admin-netresult-sys-report-layout-config.ts @@ -0,0 +1,69 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { SysReportLayoutConfig } from './sys-report-layout-config'; + /** + * 全局返回结果 + * + * @export + * @interface AdminNETResultSysReportLayoutConfig + */ +export interface AdminNETResultSysReportLayoutConfig { + + /** + * 状态码 + * + * @type {number} + * @memberof AdminNETResultSysReportLayoutConfig + */ + code?: number; + + /** + * 类型success、warning、error + * + * @type {string} + * @memberof AdminNETResultSysReportLayoutConfig + */ + type?: string | null; + + /** + * 错误信息 + * + * @type {string} + * @memberof AdminNETResultSysReportLayoutConfig + */ + message?: string | null; + + /** + * @type {SysReportLayoutConfig} + * @memberof AdminNETResultSysReportLayoutConfig + */ + result?: SysReportLayoutConfig; + + /** + * 附加数据 + * + * @type {any} + * @memberof AdminNETResultSysReportLayoutConfig + */ + extras?: any | null; + + /** + * 时间 + * + * @type {Date} + * @memberof AdminNETResultSysReportLayoutConfig + */ + time?: Date; +} diff --git a/Web/src/api-services/models/column-custom-output.ts b/Web/src/api-services/models/column-custom-output.ts new file mode 100644 index 00000000..70b890bc --- /dev/null +++ b/Web/src/api-services/models/column-custom-output.ts @@ -0,0 +1,70 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 用户表格列配置输出参数 + * + * @export + * @interface ColumnCustomOutput + */ +export interface ColumnCustomOutput { + + /** + * 用户Id + * + * @type {number} + * @memberof ColumnCustomOutput + */ + userId?: number; + + /** + * 表格Id + * + * @type {string} + * @memberof ColumnCustomOutput + */ + gridId?: string | null; + + /** + * 冻结列状态数据 + * + * @type {{ [key: string]: string; }} + * @memberof ColumnCustomOutput + */ + fixedData?: { [key: string]: string; } | null; + + /** + * 列宽状态数据 + * + * @type {{ [key: string]: number; }} + * @memberof ColumnCustomOutput + */ + resizableData?: { [key: string]: number; } | null; + + /** + * 列顺序数据 + * + * @type {{ [key: string]: number; }} + * @memberof ColumnCustomOutput + */ + sortData?: { [key: string]: number; } | null; + + /** + * 显示/隐藏列状态数据 + * + * @type {{ [key: string]: boolean; }} + * @memberof ColumnCustomOutput + */ + visibleData?: { [key: string]: boolean; } | null; +} diff --git a/Web/src/api-services/models/index.ts b/Web/src/api-services/models/index.ts index a5abeaa0..99f525f4 100644 --- a/Web/src/api-services/models/index.ts +++ b/Web/src/api-services/models/index.ts @@ -14,6 +14,9 @@ export * from './add-plugin-input'; export * from './add-pos-input'; export * from './add-print-input'; export * from './add-region-input'; +export * from './add-report-config-input'; +export * from './add-report-data-source-input'; +export * from './add-report-group-input'; export * from './add-role-input'; export * from './add-schedule-input'; export * from './add-subscribe-message-template-input'; @@ -24,11 +27,13 @@ export * from './address-family'; export * from './admin-netresult-boolean'; export * from './admin-netresult-captcha-output'; export * from './admin-netresult-chat-output'; +export * from './admin-netresult-column-custom-output'; export * from './admin-netresult-create-pay-transaction-native-output'; export * from './admin-netresult-create-pay-transaction-output'; export * from './admin-netresult-data-set'; export * from './admin-netresult-data-table'; export * from './admin-netresult-dictionary-string-string'; +export * from './admin-netresult-file-stream-result'; export * from './admin-netresult-generate-qrimage-output'; export * from './admin-netresult-generate-signature-output'; export * from './admin-netresult-get-refund-domestic-refund-by-out-refund-number-response'; @@ -50,6 +55,7 @@ export * from './admin-netresult-list-db-backup-output'; export * from './admin-netresult-list-db-column-output'; export * from './admin-netresult-list-db-output'; export * from './admin-netresult-list-db-table-info'; +export * from './admin-netresult-list-dictionary-string-object'; export * from './admin-netresult-list-enum-entity'; export * from './admin-netresult-list-enum-type-output'; export * from './admin-netresult-list-int64'; @@ -58,6 +64,7 @@ export * from './admin-netresult-list-log-vis-output'; export * from './admin-netresult-list-menu-output'; export * from './admin-netresult-list-nu-get-package'; export * from './admin-netresult-list-pos-output'; +export * from './admin-netresult-list-report-data-source-output'; export * from './admin-netresult-list-role-output'; export * from './admin-netresult-list-role-table-output'; export * from './admin-netresult-list-stat-log-output'; @@ -75,6 +82,7 @@ export * from './admin-netresult-list-sys-menu'; export * from './admin-netresult-list-sys-notice'; export * from './admin-netresult-list-sys-org'; export * from './admin-netresult-list-sys-region'; +export * from './admin-netresult-list-sys-report-group'; export * from './admin-netresult-list-sys-schedule'; export * from './admin-netresult-list-sys-user'; export * from './admin-netresult-list-sys-user-ext-org'; @@ -87,6 +95,7 @@ export * from './admin-netresult-login-user-output'; export * from './admin-netresult-model-list-output'; export * from './admin-netresult-notice-output'; export * from './admin-netresult-object'; +export * from './admin-netresult-report-config-parse-sql-output'; export * from './admin-netresult-sm-key-pair-output'; export * from './admin-netresult-sql-sugar-paged-list-chat-list-output'; export * from './admin-netresult-sql-sugar-paged-list-job-detail-output'; @@ -94,6 +103,7 @@ export * from './admin-netresult-sql-sugar-paged-list-oauth-user-output'; export * from './admin-netresult-sql-sugar-paged-list-open-access-output'; export * from './admin-netresult-sql-sugar-paged-list-page-pos-output'; export * from './admin-netresult-sql-sugar-paged-list-page-role-output'; +export * from './admin-netresult-sql-sugar-paged-list-report-config-output'; export * from './admin-netresult-sql-sugar-paged-list-sys-code-gen'; export * from './admin-netresult-sql-sugar-paged-list-sys-config'; export * from './admin-netresult-sql-sugar-paged-list-sys-config-tenant'; @@ -113,6 +123,7 @@ export * from './admin-netresult-sql-sugar-paged-list-sys-online-user'; export * from './admin-netresult-sql-sugar-paged-list-sys-plugin'; export * from './admin-netresult-sql-sugar-paged-list-sys-print'; export * from './admin-netresult-sql-sugar-paged-list-sys-region'; +export * from './admin-netresult-sql-sugar-paged-list-sys-report-data-source'; export * from './admin-netresult-sql-sugar-paged-list-sys-upgrade'; export * from './admin-netresult-sql-sugar-paged-list-sys-wechat-pay'; export * from './admin-netresult-sql-sugar-paged-list-tenant-output'; @@ -133,6 +144,7 @@ export * from './admin-netresult-sys-log-msg'; export * from './admin-netresult-sys-log-op'; export * from './admin-netresult-sys-notice'; export * from './admin-netresult-sys-print'; +export * from './admin-netresult-sys-report-layout-config'; export * from './admin-netresult-sys-schedule'; export * from './admin-netresult-sys-upgrade'; export * from './admin-netresult-sys-user'; @@ -170,6 +182,7 @@ export * from './chat-output'; export * from './cluster-status'; export * from './code-gen-config'; export * from './code-gen-type-enum'; +export * from './column-custom-output'; export * from './column-ouput'; export * from './column-relation'; export * from './compare-info'; @@ -354,6 +367,8 @@ export * from './page-pos-input'; export * from './page-pos-output'; export * from './page-print-input'; export * from './page-region-input'; +export * from './page-report-config-input'; +export * from './page-report-data-source-input'; export * from './page-role-input'; export * from './page-role-output'; export * from './page-sys-wechat-pay-input'; @@ -373,8 +388,16 @@ export * from './public-message-input'; export * from './query-region-input'; export * from './ram-info'; export * from './refund-request-input'; +export * from './report-config-ds-type-enum'; +export * from './report-config-execute-sql-script-input'; +export * from './report-config-output'; +export * from './report-config-parse-sql-input'; +export * from './report-config-parse-sql-output'; +export * from './report-data-source-output'; +export * from './reset-column-custom-input'; export * from './reset-pwd-user-input'; export * from './role-api-input'; +export * from './role-dto'; export * from './role-input'; export * from './role-menu-input'; export * from './role-org-input'; @@ -404,6 +427,7 @@ export * from './sql-sugar-paged-list-oauth-user-output'; export * from './sql-sugar-paged-list-open-access-output'; export * from './sql-sugar-paged-list-page-pos-output'; export * from './sql-sugar-paged-list-page-role-output'; +export * from './sql-sugar-paged-list-report-config-output'; export * from './sql-sugar-paged-list-sys-code-gen'; export * from './sql-sugar-paged-list-sys-config'; export * from './sql-sugar-paged-list-sys-config-tenant'; @@ -423,12 +447,14 @@ export * from './sql-sugar-paged-list-sys-online-user'; export * from './sql-sugar-paged-list-sys-plugin'; export * from './sql-sugar-paged-list-sys-print'; export * from './sql-sugar-paged-list-sys-region'; +export * from './sql-sugar-paged-list-sys-report-data-source'; export * from './sql-sugar-paged-list-sys-upgrade'; export * from './sql-sugar-paged-list-sys-wechat-pay'; export * from './sql-sugar-paged-list-tenant-output'; export * from './sql-sugar-paged-list-user-output'; export * from './stat-log-output'; export * from './status-enum'; +export * from './store-column-custom-input'; export * from './stress-test-harness-result'; export * from './stress-test-input'; export * from './struct-layout-attribute'; @@ -469,6 +495,11 @@ export * from './sys-org'; export * from './sys-plugin'; export * from './sys-print'; export * from './sys-region'; +export * from './sys-report-data-source'; +export * from './sys-report-field'; +export * from './sys-report-group'; +export * from './sys-report-layout-config'; +export * from './sys-report-param'; export * from './sys-schedule'; export * from './sys-tenant-upload-carousel-file-body'; export * from './sys-upgrade'; @@ -512,6 +543,9 @@ export * from './update-plugin-input'; export * from './update-pos-input'; export * from './update-print-input'; export * from './update-region-input'; +export * from './update-report-config-input'; +export * from './update-report-data-source-input'; +export * from './update-report-group-input'; export * from './update-role-input'; export * from './update-schedule-input'; export * from './update-sys-ldap-input'; diff --git a/Web/src/api-services/models/login-user-output.ts b/Web/src/api-services/models/login-user-output.ts index cf75ec0b..9e9523d2 100644 --- a/Web/src/api-services/models/login-user-output.ts +++ b/Web/src/api-services/models/login-user-output.ts @@ -13,6 +13,7 @@ */ import { AccountTypeEnum } from './account-type-enum'; +import { RoleDto } from './role-dto'; /** * 用户登录信息 * @@ -158,10 +159,10 @@ export interface LoginUserOutput { /** * 角色集合 * - * @type {Array} + * @type {Array} * @memberof LoginUserOutput */ - roleIds?: Array | null; + roles?: Array | null; /** * 水印文字 diff --git a/Web/src/api-services/models/page-report-config-input.ts b/Web/src/api-services/models/page-report-config-input.ts new file mode 100644 index 00000000..a64183df --- /dev/null +++ b/Web/src/api-services/models/page-report-config-input.ts @@ -0,0 +1,100 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { Filter } from './filter'; +import { Search } from './search'; + /** + * 报表配置分页输入参数 + * + * @export + * @interface PageReportConfigInput + */ +export interface PageReportConfigInput { + + /** + * @type {Search} + * @memberof PageReportConfigInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageReportConfigInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageReportConfigInput + */ + filter?: Filter; + + /** + * 当前页码 + * + * @type {number} + * @memberof PageReportConfigInput + */ + page?: number; + + /** + * 页码容量 + * + * @type {number} + * @memberof PageReportConfigInput + */ + pageSize?: number; + + /** + * 排序字段 + * + * @type {string} + * @memberof PageReportConfigInput + */ + field?: string | null; + + /** + * 排序方向 + * + * @type {string} + * @memberof PageReportConfigInput + */ + order?: string | null; + + /** + * 降序排序 + * + * @type {string} + * @memberof PageReportConfigInput + */ + descStr?: string | null; + + /** + * 名称 + * + * @type {string} + * @memberof PageReportConfigInput + */ + name?: string | null; + + /** + * 分组Id + * + * @type {number} + * @memberof PageReportConfigInput + */ + groupId?: number | null; +} diff --git a/Web/src/api-services/models/page-report-data-source-input.ts b/Web/src/api-services/models/page-report-data-source-input.ts new file mode 100644 index 00000000..af99b3d4 --- /dev/null +++ b/Web/src/api-services/models/page-report-data-source-input.ts @@ -0,0 +1,92 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { Filter } from './filter'; +import { Search } from './search'; + /** + * 报表数据源分页输入参数 + * + * @export + * @interface PageReportDataSourceInput + */ +export interface PageReportDataSourceInput { + + /** + * @type {Search} + * @memberof PageReportDataSourceInput + */ + search?: Search; + + /** + * 模糊查询关键字 + * + * @type {string} + * @memberof PageReportDataSourceInput + */ + keyword?: string | null; + + /** + * @type {Filter} + * @memberof PageReportDataSourceInput + */ + filter?: Filter; + + /** + * 当前页码 + * + * @type {number} + * @memberof PageReportDataSourceInput + */ + page?: number; + + /** + * 页码容量 + * + * @type {number} + * @memberof PageReportDataSourceInput + */ + pageSize?: number; + + /** + * 排序字段 + * + * @type {string} + * @memberof PageReportDataSourceInput + */ + field?: string | null; + + /** + * 排序方向 + * + * @type {string} + * @memberof PageReportDataSourceInput + */ + order?: string | null; + + /** + * 降序排序 + * + * @type {string} + * @memberof PageReportDataSourceInput + */ + descStr?: string | null; + + /** + * 名称 + * + * @type {string} + * @memberof PageReportDataSourceInput + */ + name?: string | null; +} diff --git a/Web/src/api-services/models/report-config-ds-type-enum.ts b/Web/src/api-services/models/report-config-ds-type-enum.ts new file mode 100644 index 00000000..5ce6bc0e --- /dev/null +++ b/Web/src/api-services/models/report-config-ds-type-enum.ts @@ -0,0 +1,24 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +/** + * 报表配置数据源类型
 Sql Sql = 0
 Api Api = 1
+ * @export + * @enum {string} + */ +export enum ReportConfigDsTypeEnum { + NUMBER_0 = 0, + NUMBER_1 = 1 +} + diff --git a/Web/src/api-services/models/report-config-execute-sql-script-input.ts b/Web/src/api-services/models/report-config-execute-sql-script-input.ts new file mode 100644 index 00000000..9861718b --- /dev/null +++ b/Web/src/api-services/models/report-config-execute-sql-script-input.ts @@ -0,0 +1,38 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 报表配置执行Sql脚本输入参数 + * + * @export + * @interface ReportConfigExecuteSqlScriptInput + */ +export interface ReportConfigExecuteSqlScriptInput { + + /** + * 主键Id + * + * @type {number} + * @memberof ReportConfigExecuteSqlScriptInput + */ + id: number; + + /** + * 执行参数 + * + * @type {{ [key: string]: any; }} + * @memberof ReportConfigExecuteSqlScriptInput + */ + execParams?: { [key: string]: any; } | null; +} diff --git a/Web/src/api-services/models/report-config-output.ts b/Web/src/api-services/models/report-config-output.ts new file mode 100644 index 00000000..c7aeeceb --- /dev/null +++ b/Web/src/api-services/models/report-config-output.ts @@ -0,0 +1,188 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { ReportConfigDsTypeEnum } from './report-config-ds-type-enum'; +import { SysReportGroup } from './sys-report-group'; + /** + * 报表配置输出参数 + * + * @export + * @interface ReportConfigOutput + */ +export interface ReportConfigOutput { + + /** + * 雪花Id + * + * @type {number} + * @memberof ReportConfigOutput + */ + id?: number; + + /** + * 创建时间 + * + * @type {Date} + * @memberof ReportConfigOutput + */ + createTime?: Date; + + /** + * 更新时间 + * + * @type {Date} + * @memberof ReportConfigOutput + */ + updateTime?: Date | null; + + /** + * 创建者Id + * + * @type {number} + * @memberof ReportConfigOutput + */ + createUserId?: number | null; + + /** + * 创建者姓名 + * + * @type {string} + * @memberof ReportConfigOutput + */ + createUserName?: string | null; + + /** + * 修改者Id + * + * @type {number} + * @memberof ReportConfigOutput + */ + updateUserId?: number | null; + + /** + * 修改者姓名 + * + * @type {string} + * @memberof ReportConfigOutput + */ + updateUserName?: string | null; + + /** + * 软删除 + * + * @type {boolean} + * @memberof ReportConfigOutput + */ + isDelete?: boolean; + + /** + * 名称 + * + * @type {string} + * @memberof ReportConfigOutput + */ + name?: string | null; + + /** + * 描述 + * + * @type {string} + * @memberof ReportConfigOutput + */ + description?: string | null; + + /** + * @type {ReportConfigDsTypeEnum} + * @memberof ReportConfigOutput + */ + dsType?: ReportConfigDsTypeEnum; + + /** + * 数据源 + * + * @type {string} + * @memberof ReportConfigOutput + */ + dataSource?: string | null; + + /** + * 分组Id + * + * @type {number} + * @memberof ReportConfigOutput + */ + groupId?: number | null; + + /** + * @type {SysReportGroup} + * @memberof ReportConfigOutput + */ + group?: SysReportGroup; + + /** + * 脚本语句 + * + * @type {string} + * @memberof ReportConfigOutput + */ + sqlScript?: string | null; + + /** + * 接口地址 + * + * @type {string} + * @memberof ReportConfigOutput + */ + apiUrl?: string | null; + + /** + * 接口请求方式 + * + * @type {string} + * @memberof ReportConfigOutput + */ + apiHttpMethod?: string | null; + + /** + * 接口参数 + * + * @type {string} + * @memberof ReportConfigOutput + */ + apiParams?: string | null; + + /** + * 参数 + * + * @type {string} + * @memberof ReportConfigOutput + */ + params?: string | null; + + /** + * 列表字段 + * + * @type {string} + * @memberof ReportConfigOutput + */ + fields?: string | null; + + /** + * 分组名称 + * + * @type {string} + * @memberof ReportConfigOutput + */ + groupName?: string | null; +} diff --git a/Web/src/api-services/models/report-config-parse-sql-input.ts b/Web/src/api-services/models/report-config-parse-sql-input.ts new file mode 100644 index 00000000..a1486901 --- /dev/null +++ b/Web/src/api-services/models/report-config-parse-sql-input.ts @@ -0,0 +1,46 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 报表配置解析Sql输入参数 + * + * @export + * @interface ReportConfigParseSqlInput + */ +export interface ReportConfigParseSqlInput { + + /** + * 数据源 + * + * @type {string} + * @memberof ReportConfigParseSqlInput + */ + dataSource?: string | null; + + /** + * 脚本语句 + * + * @type {string} + * @memberof ReportConfigParseSqlInput + */ + sqlScript?: string | null; + + /** + * 执行参数 + * + * @type {{ [key: string]: any; }} + * @memberof ReportConfigParseSqlInput + */ + execParams?: { [key: string]: any; } | null; +} diff --git a/Web/src/api-services/models/report-config-parse-sql-output.ts b/Web/src/api-services/models/report-config-parse-sql-output.ts new file mode 100644 index 00000000..b5ba5746 --- /dev/null +++ b/Web/src/api-services/models/report-config-parse-sql-output.ts @@ -0,0 +1,30 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 报表配置解析Sql输出参数 + * + * @export + * @interface ReportConfigParseSqlOutput + */ +export interface ReportConfigParseSqlOutput { + + /** + * 报表字段名称集合 + * + * @type {Array} + * @memberof ReportConfigParseSqlOutput + */ + fieldNames?: Array | null; +} diff --git a/Web/src/api-services/models/report-data-source-output.ts b/Web/src/api-services/models/report-data-source-output.ts new file mode 100644 index 00000000..d958b9bb --- /dev/null +++ b/Web/src/api-services/models/report-data-source-output.ts @@ -0,0 +1,46 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 报表数据源输出参数 + * + * @export + * @interface ReportDataSourceOutput + */ +export interface ReportDataSourceOutput { + + /** + * Id + * + * @type {string} + * @memberof ReportDataSourceOutput + */ + id?: string | null; + + /** + * 名称 + * + * @type {string} + * @memberof ReportDataSourceOutput + */ + name?: string | null; + + /** + * 是否内置 + * + * @type {boolean} + * @memberof ReportDataSourceOutput + */ + isBuildIn?: boolean; +} diff --git a/Web/src/api-services/models/reset-column-custom-input.ts b/Web/src/api-services/models/reset-column-custom-input.ts new file mode 100644 index 00000000..0a786628 --- /dev/null +++ b/Web/src/api-services/models/reset-column-custom-input.ts @@ -0,0 +1,30 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 重置用户表格列配置输入参数 + * + * @export + * @interface ResetColumnCustomInput + */ +export interface ResetColumnCustomInput { + + /** + * 表格Id + * + * @type {string} + * @memberof ResetColumnCustomInput + */ + gridId: string; +} diff --git a/Web/src/api-services/models/role-dto.ts b/Web/src/api-services/models/role-dto.ts new file mode 100644 index 00000000..bf7b21b7 --- /dev/null +++ b/Web/src/api-services/models/role-dto.ts @@ -0,0 +1,46 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 角色 + * + * @export + * @interface RoleDto + */ +export interface RoleDto { + + /** + * 角色Id + * + * @type {number} + * @memberof RoleDto + */ + id?: number; + + /** + * 名称 + * + * @type {string} + * @memberof RoleDto + */ + name?: string | null; + + /** + * 编码 + * + * @type {string} + * @memberof RoleDto + */ + code?: string | null; +} diff --git a/Web/src/api-services/models/sql-sugar-paged-list-report-config-output.ts b/Web/src/api-services/models/sql-sugar-paged-list-report-config-output.ts new file mode 100644 index 00000000..d9bc879f --- /dev/null +++ b/Web/src/api-services/models/sql-sugar-paged-list-report-config-output.ts @@ -0,0 +1,79 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { ReportConfigOutput } from './report-config-output'; + /** + * 分页泛型集合 + * + * @export + * @interface SqlSugarPagedListReportConfigOutput + */ +export interface SqlSugarPagedListReportConfigOutput { + + /** + * 页码 + * + * @type {number} + * @memberof SqlSugarPagedListReportConfigOutput + */ + page?: number; + + /** + * 页容量 + * + * @type {number} + * @memberof SqlSugarPagedListReportConfigOutput + */ + pageSize?: number; + + /** + * 总条数 + * + * @type {number} + * @memberof SqlSugarPagedListReportConfigOutput + */ + total?: number; + + /** + * 总页数 + * + * @type {number} + * @memberof SqlSugarPagedListReportConfigOutput + */ + totalPages?: number; + + /** + * 当前页集合 + * + * @type {Array} + * @memberof SqlSugarPagedListReportConfigOutput + */ + items?: Array | null; + + /** + * 是否有上一页 + * + * @type {boolean} + * @memberof SqlSugarPagedListReportConfigOutput + */ + hasPrevPage?: boolean; + + /** + * 是否有下一页 + * + * @type {boolean} + * @memberof SqlSugarPagedListReportConfigOutput + */ + hasNextPage?: boolean; +} diff --git a/Web/src/api-services/models/sql-sugar-paged-list-sys-report-data-source.ts b/Web/src/api-services/models/sql-sugar-paged-list-sys-report-data-source.ts new file mode 100644 index 00000000..3181324f --- /dev/null +++ b/Web/src/api-services/models/sql-sugar-paged-list-sys-report-data-source.ts @@ -0,0 +1,79 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { SysReportDataSource } from './sys-report-data-source'; + /** + * 分页泛型集合 + * + * @export + * @interface SqlSugarPagedListSysReportDataSource + */ +export interface SqlSugarPagedListSysReportDataSource { + + /** + * 页码 + * + * @type {number} + * @memberof SqlSugarPagedListSysReportDataSource + */ + page?: number; + + /** + * 页容量 + * + * @type {number} + * @memberof SqlSugarPagedListSysReportDataSource + */ + pageSize?: number; + + /** + * 总条数 + * + * @type {number} + * @memberof SqlSugarPagedListSysReportDataSource + */ + total?: number; + + /** + * 总页数 + * + * @type {number} + * @memberof SqlSugarPagedListSysReportDataSource + */ + totalPages?: number; + + /** + * 当前页集合 + * + * @type {Array} + * @memberof SqlSugarPagedListSysReportDataSource + */ + items?: Array | null; + + /** + * 是否有上一页 + * + * @type {boolean} + * @memberof SqlSugarPagedListSysReportDataSource + */ + hasPrevPage?: boolean; + + /** + * 是否有下一页 + * + * @type {boolean} + * @memberof SqlSugarPagedListSysReportDataSource + */ + hasNextPage?: boolean; +} diff --git a/Web/src/api-services/models/store-column-custom-input.ts b/Web/src/api-services/models/store-column-custom-input.ts new file mode 100644 index 00000000..ac9dd6ed --- /dev/null +++ b/Web/src/api-services/models/store-column-custom-input.ts @@ -0,0 +1,62 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 保存用户表格列配置输入参数 + * + * @export + * @interface StoreColumnCustomInput + */ +export interface StoreColumnCustomInput { + + /** + * 表格Id + * + * @type {string} + * @memberof StoreColumnCustomInput + */ + gridId: string; + + /** + * 冻结列状态数据 + * + * @type {{ [key: string]: string; }} + * @memberof StoreColumnCustomInput + */ + fixedData?: { [key: string]: string; } | null; + + /** + * 列宽状态数据 + * + * @type {{ [key: string]: number; }} + * @memberof StoreColumnCustomInput + */ + resizableData?: { [key: string]: number; } | null; + + /** + * 列顺序数据 + * + * @type {{ [key: string]: number; }} + * @memberof StoreColumnCustomInput + */ + sortData?: { [key: string]: number; } | null; + + /** + * 显示/隐藏列状态数据 + * + * @type {{ [key: string]: boolean; }} + * @memberof StoreColumnCustomInput + */ + visibleData?: { [key: string]: boolean; } | null; +} diff --git a/Web/src/api-services/models/sys-report-data-source.ts b/Web/src/api-services/models/sys-report-data-source.ts new file mode 100644 index 00000000..9d6eb5ad --- /dev/null +++ b/Web/src/api-services/models/sys-report-data-source.ts @@ -0,0 +1,118 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 系统报表数据源 + * + * @export + * @interface SysReportDataSource + */ +export interface SysReportDataSource { + + /** + * 雪花Id + * + * @type {number} + * @memberof SysReportDataSource + */ + id?: number; + + /** + * 创建时间 + * + * @type {Date} + * @memberof SysReportDataSource + */ + createTime?: Date; + + /** + * 更新时间 + * + * @type {Date} + * @memberof SysReportDataSource + */ + updateTime?: Date | null; + + /** + * 创建者Id + * + * @type {number} + * @memberof SysReportDataSource + */ + createUserId?: number | null; + + /** + * 创建者姓名 + * + * @type {string} + * @memberof SysReportDataSource + */ + createUserName?: string | null; + + /** + * 修改者Id + * + * @type {number} + * @memberof SysReportDataSource + */ + updateUserId?: number | null; + + /** + * 修改者姓名 + * + * @type {string} + * @memberof SysReportDataSource + */ + updateUserName?: string | null; + + /** + * 软删除 + * + * @type {boolean} + * @memberof SysReportDataSource + */ + isDelete?: boolean; + + /** + * 名称 + * + * @type {string} + * @memberof SysReportDataSource + */ + name?: string | null; + + /** + * 数据库类型 + * + * @type {string} + * @memberof SysReportDataSource + */ + dbType?: string | null; + + /** + * 连接字符串 + * + * @type {string} + * @memberof SysReportDataSource + */ + connectionString?: string | null; + + /** + * 备注 + * + * @type {string} + * @memberof SysReportDataSource + */ + remark?: string | null; +} diff --git a/Web/src/api-services/models/sys-report-field.ts b/Web/src/api-services/models/sys-report-field.ts new file mode 100644 index 00000000..214c2c9b --- /dev/null +++ b/Web/src/api-services/models/sys-report-field.ts @@ -0,0 +1,70 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 报表字段 + * + * @export + * @interface SysReportField + */ +export interface SysReportField { + + /** + * 字段名 + * + * @type {string} + * @memberof SysReportField + */ + fieldName?: string | null; + + /** + * 字段标题 + * + * @type {string} + * @memberof SysReportField + */ + title?: string | null; + + /** + * 是否合计 + * + * @type {boolean} + * @memberof SysReportField + */ + isSummary?: boolean; + + /** + * 是否显示 + * + * @type {boolean} + * @memberof SysReportField + */ + visible?: boolean; + + /** + * 分组标题 + * + * @type {string} + * @memberof SysReportField + */ + groupTitle?: string | null; + + /** + * 列宽度 + * + * @type {number} + * @memberof SysReportField + */ + width?: number; +} diff --git a/Web/src/api-services/models/sys-report-group.ts b/Web/src/api-services/models/sys-report-group.ts new file mode 100644 index 00000000..cc3b5f68 --- /dev/null +++ b/Web/src/api-services/models/sys-report-group.ts @@ -0,0 +1,102 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 系统报表分组 + * + * @export + * @interface SysReportGroup + */ +export interface SysReportGroup { + + /** + * 雪花Id + * + * @type {number} + * @memberof SysReportGroup + */ + id?: number; + + /** + * 创建时间 + * + * @type {Date} + * @memberof SysReportGroup + */ + createTime?: Date; + + /** + * 更新时间 + * + * @type {Date} + * @memberof SysReportGroup + */ + updateTime?: Date | null; + + /** + * 创建者Id + * + * @type {number} + * @memberof SysReportGroup + */ + createUserId?: number | null; + + /** + * 创建者姓名 + * + * @type {string} + * @memberof SysReportGroup + */ + createUserName?: string | null; + + /** + * 修改者Id + * + * @type {number} + * @memberof SysReportGroup + */ + updateUserId?: number | null; + + /** + * 修改者姓名 + * + * @type {string} + * @memberof SysReportGroup + */ + updateUserName?: string | null; + + /** + * 软删除 + * + * @type {boolean} + * @memberof SysReportGroup + */ + isDelete?: boolean; + + /** + * 编码 + * + * @type {string} + * @memberof SysReportGroup + */ + number?: string | null; + + /** + * 名称 + * + * @type {string} + * @memberof SysReportGroup + */ + name?: string | null; +} diff --git a/Web/src/api-services/models/sys-report-layout-config.ts b/Web/src/api-services/models/sys-report-layout-config.ts new file mode 100644 index 00000000..ac96fa51 --- /dev/null +++ b/Web/src/api-services/models/sys-report-layout-config.ts @@ -0,0 +1,40 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { SysReportField } from './sys-report-field'; +import { SysReportParam } from './sys-report-param'; + /** + * 报表布局配置 + * + * @export + * @interface SysReportLayoutConfig + */ +export interface SysReportLayoutConfig { + + /** + * 报表字段集合 + * + * @type {Array} + * @memberof SysReportLayoutConfig + */ + fields?: Array | null; + + /** + * 报表参数集合 + * + * @type {Array} + * @memberof SysReportLayoutConfig + */ + params?: Array | null; +} diff --git a/Web/src/api-services/models/sys-report-param.ts b/Web/src/api-services/models/sys-report-param.ts new file mode 100644 index 00000000..63bda48e --- /dev/null +++ b/Web/src/api-services/models/sys-report-param.ts @@ -0,0 +1,54 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 报表参数 + * + * @export + * @interface SysReportParam + */ +export interface SysReportParam { + + /** + * 参数名 + * + * @type {string} + * @memberof SysReportParam + */ + paramName?: string | null; + + /** + * 参数标题 + * + * @type {string} + * @memberof SysReportParam + */ + title?: string | null; + + /** + * 输入控件类型 + * + * @type {string} + * @memberof SysReportParam + */ + inputCtrl?: string | null; + + /** + * 默认值 + * + * @type {any} + * @memberof SysReportParam + */ + defaultValue?: any | null; +} diff --git a/Web/src/api-services/models/update-report-config-input.ts b/Web/src/api-services/models/update-report-config-input.ts new file mode 100644 index 00000000..d7a63ac8 --- /dev/null +++ b/Web/src/api-services/models/update-report-config-input.ts @@ -0,0 +1,180 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +import { ReportConfigDsTypeEnum } from './report-config-ds-type-enum'; +import { SysReportGroup } from './sys-report-group'; + /** + * + * + * @export + * @interface UpdateReportConfigInput + */ +export interface UpdateReportConfigInput { + + /** + * 雪花Id + * + * @type {number} + * @memberof UpdateReportConfigInput + */ + id?: number; + + /** + * 创建时间 + * + * @type {Date} + * @memberof UpdateReportConfigInput + */ + createTime?: Date; + + /** + * 更新时间 + * + * @type {Date} + * @memberof UpdateReportConfigInput + */ + updateTime?: Date | null; + + /** + * 创建者Id + * + * @type {number} + * @memberof UpdateReportConfigInput + */ + createUserId?: number | null; + + /** + * 创建者姓名 + * + * @type {string} + * @memberof UpdateReportConfigInput + */ + createUserName?: string | null; + + /** + * 修改者Id + * + * @type {number} + * @memberof UpdateReportConfigInput + */ + updateUserId?: number | null; + + /** + * 修改者姓名 + * + * @type {string} + * @memberof UpdateReportConfigInput + */ + updateUserName?: string | null; + + /** + * 软删除 + * + * @type {boolean} + * @memberof UpdateReportConfigInput + */ + isDelete?: boolean; + + /** + * 名称 + * + * @type {string} + * @memberof UpdateReportConfigInput + */ + name?: string | null; + + /** + * 描述 + * + * @type {string} + * @memberof UpdateReportConfigInput + */ + description?: string | null; + + /** + * @type {ReportConfigDsTypeEnum} + * @memberof UpdateReportConfigInput + */ + dsType?: ReportConfigDsTypeEnum; + + /** + * 数据源 + * + * @type {string} + * @memberof UpdateReportConfigInput + */ + dataSource?: string | null; + + /** + * 分组Id + * + * @type {number} + * @memberof UpdateReportConfigInput + */ + groupId?: number | null; + + /** + * @type {SysReportGroup} + * @memberof UpdateReportConfigInput + */ + group?: SysReportGroup; + + /** + * 脚本语句 + * + * @type {string} + * @memberof UpdateReportConfigInput + */ + sqlScript?: string | null; + + /** + * 接口地址 + * + * @type {string} + * @memberof UpdateReportConfigInput + */ + apiUrl?: string | null; + + /** + * 接口请求方式 + * + * @type {string} + * @memberof UpdateReportConfigInput + */ + apiHttpMethod?: string | null; + + /** + * 接口参数 + * + * @type {string} + * @memberof UpdateReportConfigInput + */ + apiParams?: string | null; + + /** + * 参数 + * + * @type {string} + * @memberof UpdateReportConfigInput + */ + params?: string | null; + + /** + * 列表字段 + * + * @type {string} + * @memberof UpdateReportConfigInput + */ + fields?: string | null; +} diff --git a/Web/src/api-services/models/update-report-data-source-input.ts b/Web/src/api-services/models/update-report-data-source-input.ts new file mode 100644 index 00000000..f54a3001 --- /dev/null +++ b/Web/src/api-services/models/update-report-data-source-input.ts @@ -0,0 +1,118 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * + * + * @export + * @interface UpdateReportDataSourceInput + */ +export interface UpdateReportDataSourceInput { + + /** + * 雪花Id + * + * @type {number} + * @memberof UpdateReportDataSourceInput + */ + id?: number; + + /** + * 创建时间 + * + * @type {Date} + * @memberof UpdateReportDataSourceInput + */ + createTime?: Date; + + /** + * 更新时间 + * + * @type {Date} + * @memberof UpdateReportDataSourceInput + */ + updateTime?: Date | null; + + /** + * 创建者Id + * + * @type {number} + * @memberof UpdateReportDataSourceInput + */ + createUserId?: number | null; + + /** + * 创建者姓名 + * + * @type {string} + * @memberof UpdateReportDataSourceInput + */ + createUserName?: string | null; + + /** + * 修改者Id + * + * @type {number} + * @memberof UpdateReportDataSourceInput + */ + updateUserId?: number | null; + + /** + * 修改者姓名 + * + * @type {string} + * @memberof UpdateReportDataSourceInput + */ + updateUserName?: string | null; + + /** + * 软删除 + * + * @type {boolean} + * @memberof UpdateReportDataSourceInput + */ + isDelete?: boolean; + + /** + * 名称 + * + * @type {string} + * @memberof UpdateReportDataSourceInput + */ + name?: string | null; + + /** + * 数据库类型 + * + * @type {string} + * @memberof UpdateReportDataSourceInput + */ + dbType?: string | null; + + /** + * 连接字符串 + * + * @type {string} + * @memberof UpdateReportDataSourceInput + */ + connectionString?: string | null; + + /** + * 备注 + * + * @type {string} + * @memberof UpdateReportDataSourceInput + */ + remark?: string | null; +} diff --git a/Web/src/api-services/models/update-report-group-input.ts b/Web/src/api-services/models/update-report-group-input.ts new file mode 100644 index 00000000..46ffd20d --- /dev/null +++ b/Web/src/api-services/models/update-report-group-input.ts @@ -0,0 +1,102 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * + * + * @export + * @interface UpdateReportGroupInput + */ +export interface UpdateReportGroupInput { + + /** + * 雪花Id + * + * @type {number} + * @memberof UpdateReportGroupInput + */ + id?: number; + + /** + * 创建时间 + * + * @type {Date} + * @memberof UpdateReportGroupInput + */ + createTime?: Date; + + /** + * 更新时间 + * + * @type {Date} + * @memberof UpdateReportGroupInput + */ + updateTime?: Date | null; + + /** + * 创建者Id + * + * @type {number} + * @memberof UpdateReportGroupInput + */ + createUserId?: number | null; + + /** + * 创建者姓名 + * + * @type {string} + * @memberof UpdateReportGroupInput + */ + createUserName?: string | null; + + /** + * 修改者Id + * + * @type {number} + * @memberof UpdateReportGroupInput + */ + updateUserId?: number | null; + + /** + * 修改者姓名 + * + * @type {string} + * @memberof UpdateReportGroupInput + */ + updateUserName?: string | null; + + /** + * 软删除 + * + * @type {boolean} + * @memberof UpdateReportGroupInput + */ + isDelete?: boolean; + + /** + * 编码 + * + * @type {string} + * @memberof UpdateReportGroupInput + */ + number?: string | null; + + /** + * 名称 + * + * @type {string} + * @memberof UpdateReportGroupInput + */ + name?: string | null; +} diff --git a/Web/public/chat.png b/Web/src/assets/chat.png similarity index 100% rename from Web/public/chat.png rename to Web/src/assets/chat.png diff --git a/Web/src/components/editor/index.vue b/Web/src/components/editor/index.vue index 997d3887..3b939a8d 100644 --- a/Web/src/components/editor/index.vue +++ b/Web/src/components/editor/index.vue @@ -62,8 +62,9 @@ const state = reactive({ getAPI(SysFileApi) .apiSysFileUploadFilePostForm(file) .then(({ data }) => { - if (data.type == 'success' && data.result) { - editorRef.value.insertNode({ type: 'image', src: '/' + data.result.url, alt: data.result.fileName, href: '/' + data.result.url, children: [{ text: '' }] }); + if (data.type == 'success' && data.result) { + let url = data.result.url?.indexOf('http') !== 0 ? '/' + data.result.url : data.result.url; + editorRef.value.insertNode({ type: 'image', src: url, alt: data.result.fileName, href: url, children: [{ text: '' }] }); } else { ElMessage.error('上传失败!'); } diff --git a/Web/src/components/table/modifyRecord.vue b/Web/src/components/table/modifyRecord.vue index bfefc040..036941db 100644 --- a/Web/src/components/table/modifyRecord.vue +++ b/Web/src/components/table/modifyRecord.vue @@ -38,6 +38,24 @@ {{ props.data.updateTime ?? t('message.list.none') }} + + + + {{ props.data.createOrgName ?? t('message.list.none') }} + + + + {{ props.data.tenantId ?? t('message.list.none') }} + + @@ -59,6 +63,7 @@ import VueJsonPretty from 'vue-json-pretty'; import 'vue-json-pretty/lib/styles.css'; import { Splitpanes, Pane } from 'splitpanes'; import 'splitpanes/dist/splitpanes.css'; +import { useI18n } from 'vue-i18n'; import NoticeBar from '/@/components/noticeBar/index.vue'; @@ -67,6 +72,7 @@ const scEcharts = defineAsyncComponent(() => import('/@/components/scEcharts/ind import { getAPI } from '/@/utils/axios-utils'; import { SysCacheApi } from '/@/api-services'; +const { t } = useI18n(); const treeRef = ref>(); const currentNode = ref({}); const state = reactive({ diff --git a/Web/src/views/system/codeGen/index.vue b/Web/src/views/system/codeGen/index.vue index 286b580f..7b0685a4 100644 --- a/Web/src/views/system/codeGen/index.vue +++ b/Web/src/views/system/codeGen/index.vue @@ -220,6 +220,10 @@ const gridEvents: VxeGridListeners = { state.localPageParam.defaultSort = { field: field, order: order!, descStr: 'desc' }; Local.set(localPageParamKey, state.localPageParam); }, + // 双击行事件 + async cellDblclick({ row }) { + await handleEdit(row); + }, }; // 打开配置 diff --git a/Web/src/views/system/config/index.vue b/Web/src/views/system/config/index.vue index 03174a22..d6a43ffd 100644 --- a/Web/src/views/system/config/index.vue +++ b/Web/src/views/system/config/index.vue @@ -73,6 +73,7 @@ import { ElMessageBox, ElMessage } from 'element-plus'; import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table'; import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook'; import { Local } from '/@/utils/storage'; +import { auth } from '/@/utils/authFunction'; import EditConfig from '/@/views/system/config/component/editConfig.vue'; import ModifyRecord from '/@/components/table/modifyRecord.vue'; @@ -200,6 +201,10 @@ const gridEvents: VxeGridListeners = { state.localPageParam.defaultSort = { field: field, order: order!, descStr: 'desc' }; Local.set(localPageParamKey, state.localPageParam); }, + // 双击行事件 + async cellDblclick({ row }) { + if (auth('sysConfig/update')) await handleEdit(row); + }, }; // 获取分组 diff --git a/Web/src/views/system/database/index.vue b/Web/src/views/system/database/index.vue index 956b0dab..bca3533c 100644 --- a/Web/src/views/system/database/index.vue +++ b/Web/src/views/system/database/index.vue @@ -22,7 +22,7 @@ - +