diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b31ce6c..bed0302d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,62 @@ + + +## v8.1 + +* [重磅] 统一后端返回格式response.result调整为response.data +* [重磅] 表格组件增加排序功能 +* [优化] 持续优化代码 + +## v8.0 + +* [重磅] 开源十周年特别版! +* [重磅] 全面开源原付费vue2版本源码及文档,免费使用。 +* [重磅] 删除原有mvc项目,从此以后只有前后端分离。 + + +## v7.6 + +* [重磅] 分离会签和网关功能,详情请查看工作流中的概念 +* [优化] 前后端统一流程节点类型。详情请查看文档流程相关代码-流程模板 +* [优化] 修复顺序加签 + +## v7.5 + +* [新增] 流程执行节点支持通过Sql配置用户 +* [优化] 流程节点设置json对象统一为datas字段 +* [优化] 优化layui样式 + +## v7.4 + +* [新增] 代码生成加上外部数据源支持; +* [新增] 新增动态API功能; +* [优化] 流程模板调整为sqlsugar; + +## v7.3 + +* [新增] 新增API鉴权功能 +* [优化] 优化vue3代码生成; + +## v7.2 + +* [重磅]流程增加任意节点撤回审批功能 +* [重磅]全面优化数据库初始脚本,SqlServer采用帕斯卡命名,MySql/pg采用小写命名,Oracle采用大写 +* [重磅]优化layui点击行可选中 + +## v7.1 + +* [重磅]全面优化对Oracle数据库的支持 +* [优化]FIX issue #IBLX2E:目前Oracle工作流列表不能加载 目前Oracle工作流列表不能加载 +* [优化]流程实例历史操作记录 + +## v7.0 + +- **新特性** + + - [新增] 全面支持.Net 9 + - [新增] 新增Dockerfile支持 + - [新增] 修复vue3代码生成部分bug + + ## v6.5 - **新特性** diff --git a/Infrastructure/Define.cs b/Infrastructure/Define.cs index 4b0d4714..69ccbd05 100644 --- a/Infrastructure/Define.cs +++ b/Infrastructure/Define.cs @@ -5,6 +5,11 @@ /// public static class Define { + /// + /// 默认租户ID + /// + public const string DEFAULT_TENANT_ID = "OpenAuthDBContext"; + //Relevance关联KEY /// /// 用户角色关联KEY diff --git a/Infrastructure/Extensions/AutofacManager/AutofacContainerModule.cs b/Infrastructure/Extensions/AutofacManager/AutofacContainerModule.cs index 8585aaad..12c241a2 100644 --- a/Infrastructure/Extensions/AutofacManager/AutofacContainerModule.cs +++ b/Infrastructure/Extensions/AutofacManager/AutofacContainerModule.cs @@ -16,7 +16,7 @@ namespace Infrastructure.Extensions.AutofacManager public static TService GetService() where TService:class { Type typeParameterType = typeof(TService); - return (TService)_provider.GetService(typeParameterType); + return (TService)_provider?.GetService(typeParameterType); } } } diff --git a/Infrastructure/Utilities/HttpContextUtil.cs b/Infrastructure/Utilities/HttpContextUtil.cs index ef988655..0e8b6c97 100644 --- a/Infrastructure/Utilities/HttpContextUtil.cs +++ b/Infrastructure/Utilities/HttpContextUtil.cs @@ -5,9 +5,10 @@ namespace Infrastructure.Utilities { public static class HttpContextUtil { - private static IHttpContextAccessor _accessor=AutofacContainerModule.GetService(); + // 不要在静态初始化时获取IHttpContextAccessor,而是在需要时获取 + private static IHttpContextAccessor _accessor => AutofacContainerModule.GetService(); - public static Microsoft.AspNetCore.Http.HttpContext Current => _accessor.HttpContext; + public static Microsoft.AspNetCore.Http.HttpContext Current => _accessor?.HttpContext; /// /// 获取租户ID @@ -15,7 +16,7 @@ namespace Infrastructure.Utilities /// public static string GetTenantId(this IHttpContextAccessor accessor) { - string tenantId = "OpenAuthDBContext"; + string tenantId = Define.DEFAULT_TENANT_ID; if (accessor != null && accessor.HttpContext != null) { diff --git a/OpenAuth.App/Base/SqlSugarBaseApp.cs b/OpenAuth.App/Base/SqlSugarBaseApp.cs index a9f544d3..b9727b9c 100644 --- a/OpenAuth.App/Base/SqlSugarBaseApp.cs +++ b/OpenAuth.App/Base/SqlSugarBaseApp.cs @@ -1,11 +1,16 @@ using System; using System.Linq; using Infrastructure; +using Infrastructure.Utilities; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; using OpenAuth.App.Interface; using OpenAuth.Repository; using OpenAuth.Repository.Core; using OpenAuth.Repository.Domain; using SqlSugar; +using Autofac; +using Infrastructure.Extensions.AutofacManager; namespace OpenAuth.App { @@ -21,8 +26,23 @@ namespace OpenAuth.App protected IAuth _auth; + /// + /// 保持向后兼容的构造函数,避免修改子类 + /// public SqlSugarBaseApp(ISqlSugarClient client, IAuth auth) { + string tenantId = Define.DEFAULT_TENANT_ID; + var httpContextAccessor = AutofacContainerModule.GetService(); + if (httpContextAccessor != null) + { + tenantId = httpContextAccessor.GetTenantId(); + } + + if(tenantId != Define.DEFAULT_TENANT_ID) //如果不是默认租户,则使用租户id获取连接 + { + client = client.AsTenant().GetConnection(tenantId); + } + Repository = new SqlSugarRepository(client); //这里用new而不用注入,可以保证client和repository用的是同一个client SugarClient = client; _auth = auth; diff --git a/OpenAuth.Identity/Startup.cs b/OpenAuth.Identity/Startup.cs index 341b2e79..7386dcd5 100644 --- a/OpenAuth.Identity/Startup.cs +++ b/OpenAuth.Identity/Startup.cs @@ -76,8 +76,8 @@ namespace OpenAuth.IdentityServer //在startup里面只能通过这种方式获取到appsettings里面的值,不能用IOptions😰 var dbtypes = ((ConfigurationSection)Configuration.GetSection("AppSetting:DbTypes")).GetChildren() .ToDictionary(x => x.Key, x => x.Value); - var dbType = dbtypes["OpenAuthDBContext"]; - var connectionString = Configuration.GetConnectionString("OpenAuthDBContext"); + var dbType = dbtypes[Define.DEFAULT_TENANT_ID]; + var connectionString = Configuration.GetConnectionString(Define.DEFAULT_TENANT_ID); if (dbType == Define.DBTYPE_SQLSERVER) { services.AddDbContext(options => diff --git a/OpenAuth.WebApi/Startup.cs b/OpenAuth.WebApi/Startup.cs index 26b87310..d50cb7a7 100644 --- a/OpenAuth.WebApi/Startup.cs +++ b/OpenAuth.WebApi/Startup.cs @@ -92,7 +92,7 @@ namespace OpenAuth.WebApi logger.LogInformation($"api doc basepath:{AppContext.BaseDirectory}"); foreach (var name in Directory.GetFiles(AppContext.BaseDirectory, "*.*", - SearchOption.AllDirectories).Where(f => Path.GetExtension(f).ToLower() == ".xml")) + SearchOption.AllDirectories).Where(f => Path.GetExtension(f).ToLower() == ".xml")) { option.IncludeXmlComments(name, includeControllerXmlComments: true); // logger.LogInformation($"find api file{name}"); @@ -126,9 +126,6 @@ namespace OpenAuth.WebApi services.AddControllers(option => { option.Filters.Add(); }) .ConfigureApiBehaviorOptions(options => { - // 禁用自动模态验证 - // options.SuppressModelStateInvalidFilter = true; - //启动WebAPI自动模态验证,处理返回值 options.InvalidModelStateResponseFactory = (ActionContext context) => { @@ -146,67 +143,77 @@ namespace OpenAuth.WebApi }); services.AddMemoryCache(); services.AddCors(); -// todo:如果正式 环境请用下面的方式限制随意访问跨域 -// var origins = new [] -// { -// "http://localhost:1803", -// "http://localhost:52789" -// }; -// if (Environment.IsProduction()) -// { -// origins = new [] -// { -// "http://demo.openauth.net.cn:1803", -// "http://demo.openauth.net.cn:52789" -// }; -// } -// services.AddCors(option=>option.AddPolicy("cors", policy => -// policy.AllowAnyHeader().AllowAnyMethod().AllowCredentials().WithOrigins(origins))); - - //在startup里面只能通过这种方式获取到appsettings里面的值,不能用IOptions😰 - var dbtypes = ((ConfigurationSection) Configuration.GetSection("AppSetting:DbTypes")).GetChildren() - .ToDictionary(x => x.Key, x => x.Value); - var connstr = "OpenAuthDBContext"; - var connectionString = Configuration.GetConnectionString(connstr); - logger.LogInformation($"系统配置的数据库类型:{JsonHelper.Instance.Serialize(dbtypes[connstr])},连接字符串:{connectionString}"); services.AddDbContext(); services.AddHttpClient(); services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo(Configuration["DataProtection"])); + //在startup里面只能通过这种方式获取到appsettings里面的值,不能用IOptions😰 + var dbtypes = ((ConfigurationSection) Configuration.GetSection("AppSetting:DbTypes")).GetChildren() + .ToDictionary(x => x.Key, x => x.Value); var sqlsugarTypes = UtilMethods.EnumToDictionary(); - var dbType = sqlsugarTypes.FirstOrDefault(it => - dbtypes[connstr].ToLower().Contains(it.Key)); - services.AddScoped(s => { - var sqlSugar = new SqlSugarClient(new ConnectionConfig() + // 获取所有连接字符串配置 + var connectionStrings = Configuration.GetSection("ConnectionStrings").GetChildren() + .ToDictionary(x => x.Key, x => x.Value); + + // 准备ConnectionConfig列表 + var connectionConfigs = new List(); + + // 遍历所有连接字符串 + foreach (var conn in connectionStrings) { - DbType = dbType.Value, - ConnectionString = connectionString, - IsAutoCloseConnection = true - }, db => { db.Aop.OnLogExecuting = (sql, pars) => { logger.LogInformation(sql); }; }); - - if(dbType.Value != SqlSugar.DbType.PostgreSQL){ - return sqlSugar; - } - - // 配置bool类型转换为smallint - sqlSugar.Aop.OnExecutingChangeSql = (sql, parameters) => - { - foreach (var param in parameters) + // 获取对应的数据库类型 + var connDbType = dbtypes.ContainsKey(conn.Key) ? + sqlsugarTypes.FirstOrDefault(it => dbtypes[conn.Key].ToLower().Contains(it.Key)).Value : + DbType.SqlServer; // 如果没有定义DbType,使用默认类型 + + // 创建连接配置 + var config = new ConnectionConfig { - if (param.Value is bool boolValue) - { - param.DbType = System.Data.DbType.Int16; - // 将 bool 转换为 smallint - param.Value = boolValue ? (short)1 : (short)0; - } + DbType = connDbType, + ConnectionString = conn.Value, + IsAutoCloseConnection = true, + }; + + // 如果不是默认连接,设置ConfigId + if (conn.Key != Define.DEFAULT_TENANT_ID) + { + config.ConfigId = conn.Key; } - // 返回修改后的 SQL 和参数 - return new System.Collections.Generic.KeyValuePair(sql, parameters); - }; + + connectionConfigs.Add(config); + logger.LogInformation($"添加数据库连接: {conn.Key} / {(dbtypes.ContainsKey(conn.Key) ? dbtypes[conn.Key] : "未指定类型")},连接字符串:{conn.Value}"); + } + + var sqlSugar = new SqlSugarClient(connectionConfigs); + + // 配置PostgreSQL数据库处理 + foreach (var connConfig in connectionConfigs) + { + if(connConfig.DbType == SqlSugar.DbType.PostgreSQL) + { + // 配置bool类型转换为smallint + sqlSugar.Aop.OnExecutingChangeSql = (sql, parameters) => + { + foreach (var param in parameters) + { + if (param.Value is bool boolValue) + { + param.DbType = System.Data.DbType.Int16; + // 将 bool 转换为 smallint + param.Value = boolValue ? (short)1 : (short)0; + } + } + // 返回修改后的 SQL 和参数 + return new System.Collections.Generic.KeyValuePair(sql, parameters); + }; + break; // 找到一个PostgreSQL连接后就设置一次即可 + } + } + return sqlSugar; });