diff --git a/apihost/Tnb.API.Entry/Configurations/App.json b/apihost/Tnb.API.Entry/Configurations/App.json
index b0b35652..88325a5f 100644
--- a/apihost/Tnb.API.Entry/Configurations/App.json
+++ b/apihost/Tnb.API.Entry/Configurations/App.json
@@ -4,15 +4,88 @@
//系统文件路径
"SystemPath": "D:\\ToTong\\tnb\\Resources",
//微信公众号允许上传文件类型
- "MPUploadFileType": [ "bmp", "png", "jpeg", "jpg", "gif", "mp3", "wma", "wav", "amr", "mp4" ],
+ "MPUploadFileType": [
+ "bmp",
+ "png",
+ "jpeg",
+ "jpg",
+ "gif",
+ "mp3",
+ "wma",
+ "wav",
+ "amr",
+ "mp4"
+ ],
//微信允许上传文件类型
- "WeChatUploadFileType": [ "jpg", "png", "doc", "docx", "ppt", "pptx", "xls", "xlsx", "pdf", "txt", "rar", "zip", "csv", "amr", "mp4" ],
+ "WeChatUploadFileType": [
+ "jpg",
+ "png",
+ "doc",
+ "docx",
+ "ppt",
+ "pptx",
+ "xls",
+ "xlsx",
+ "pdf",
+ "txt",
+ "rar",
+ "zip",
+ "csv",
+ "amr",
+ "mp4"
+ ],
//允许图片类型
- "AllowUploadImageType": [ "jpg", "gif", "png", "bmp", "jpeg", "tiff", "psd", "swf", "svg", "pcx", "dxf", "wmf", "emf", "lic", "eps", "tga" ],
+ "AllowUploadImageType": [
+ "jpg",
+ "gif",
+ "png",
+ "bmp",
+ "jpeg",
+ "tiff",
+ "psd",
+ "swf",
+ "svg",
+ "pcx",
+ "dxf",
+ "wmf",
+ "emf",
+ "lic",
+ "eps",
+ "tga"
+ ],
//允许上传文件类型
- "AllowUploadFileType": [ "jpg", "mp3", "gif", "png", "bmp", "jpeg", "doc", "docx", "ppt", "pptx", "xls", "xlsx", "pdf", "txt", "rar", "zip", "csv" ],
+ "AllowUploadFileType": [
+ "jpg",
+ "mp3",
+ "gif",
+ "png",
+ "bmp",
+ "jpeg",
+ "doc",
+ "docx",
+ "ppt",
+ "pptx",
+ "xls",
+ "xlsx",
+ "pdf",
+ "txt",
+ "rar",
+ "zip",
+ "csv"
+ ],
//过滤上传文件名称特殊字符
- "SpecialString": [ "/", "<", ">", "|", "?", "\\", ":", "\"", "*", "_" ],
+ "SpecialString": [
+ "/",
+ "<",
+ ">",
+ "|",
+ "?",
+ "\\",
+ ":",
+ "\"",
+ "*",
+ "_"
+ ],
"PreviewType": "kkfile", //文件预览方式 (kkfile,yozo)默认使用kkfile
"KKFileDomain": "http://127.0.0.1:30090/FileServer",
"Domain": "http://yinmai.tpddns.cn:7772",
@@ -21,18 +94,52 @@
"domainKey": "57462250284462899305150",
"UploadAPI": "http://dmc.yozocloud.cn/api/file/http?fileUrl={0}&appId={1}&sign={2}", //上传接口
"DownloadAPI": "http://eic.yozocloud.cn/api/view/file?fileVersionId={0}&appId={1}&sign={2}", //预览接口
- "AppId": "yozoAQh5dPSt6063", //应用Id
- "AppKey": "6365bfbd733fce644fd7ac0aaeca" //签名
+ "AppId": "yozoAQh5dPSt6063", // 应用Id
+ "AppKey": "6365bfbd733fce644fd7ac0aaeca" // 签名
},
- //================== 系统错误邮件报告反馈相关 ============================== -->
- //软件的错误报告
+ // ================== 系统错误邮件报告反馈相关 ============================== -->
+ // 软件的错误报告
"ErrorReport": false,
//软件的错误报告发给谁
"ErrorReportTo": "tuotong_tech@163.com"
},
+ // ================== 单点登录配置(和其他登录方式 只能二选一) ============================== -->
+ "OAuth": {
+ "Enabled": false, // 开启后将支持单点登录, 前端与后端都不可使用普通模式登录
+ "LoginPath": "http://192.168.20.119:5000/api/oauth/Login", // 前端登录页面访问登录接口进行单点登录页面跳转, 需要与身份管理系统中的 JNPF-Auth2、JNPF-CAS中的认证地址一致
+ "SucessFrontUrl": "http://192.168.20.119:3000/sso", // 从单点登录中心直接访问JNPF时登录成功后跳转的前端页面
+ "DefaultSSO": "auth2", // 默认接口
+ "TicketTimeout": 5, // 缓存过期时间 / 分钟
+ "TicketOutMessage": false, // 是否前端输出消息
+ "SSO": {
+ "auth2": {
+ "enabled": true,
+ "clientId": "747887288041603072",
+ "clientSecret": "MYgMMjIwNzIwMjIxNTU4MTAxNzQlKQ",
+ "authorizeUrl": "https://192.168.20.133:8527/sign/authz/oauth/v20/authorize",
+ "accessTokenUrl": "https://192.168.20.133:8527/sign/authz/oauth/v20/token",
+ "userInfoUrl": "https://192.168.20.133:8527/sign/api/oauth/v20/me"
+ },
+ "cas": {
+ "enabled": true,
+ "serverLoginUrl": "https://sso.test.jnpf.work/sign/authz/cas/login",
+ "serverValidateUrl": "https://sso.test.jnpf.work/sign/authz/cas"
+ }
+ },
+ "Pull": {
+ "Enabled": true,
+ "CreateRestAddress": "http://192.168.20.133:9526/sso-mgt-api/api/idm/Account",
+ "ReplaceRestAddress": "http://192.168.20.133:9526/sso-mgt-api/api/idm/Account",
+ "ChangePasswordRestAddress": "http://192.168.20.133:9526/sso-mgt-api/api/idm/Account/changePassword",
+ "DeleteRestAddress": "http://192.168.20.133:9526/sso-mgt-api/api/idm/Account",
+ "CredentialType": "Basic",
+ "UserName": "747887288041603072",
+ "Password": "MYgMMjIwNzIwMjIxNTU4MTAxNzQlKQ"
+ }
+ },
//================== 第三方登录配置 ============================== -->
"Socials": {
- "SocialsEnabled": true,
+ "SocialsEnabled": false,
"DoMain": "https://562f45p309.goho.co/dev", // 外网能访问的地址(域名), 回调的时候拼接接口地址用
"Config": [
{
@@ -76,8 +183,9 @@
},
//================== 消息跳转配置 ============================== -->
"Message": {
- "DoMainPc": "http://127.0.0.1:3000", // 前端PC外网能访问的地址(域名), 回调的时候拼接接口地址用
- "DoMainApp": "http://127.0.0.1:3000", // 前端App外网能访问的地址(域名), 回调的时候拼接接口地址用
+ "ApiDoMain": "http://localhost:5000", // 后端Api路径 (发布时与DoMainPc一致)
+ "DoMainPc": "http://localhost:3000", // 前端PC外网能访问的地址(域名), 回调的时候拼接接口地址用
+ "DoMainApp": "http://localhost:8081", // 前端App外网能访问的地址(域名), 回调的时候拼接接口地址用
"AppPushUrl": "https://8e84eea8-6922-4033-8e86-67ad7442e692.bspapp.com/unipush"
}
}
\ No newline at end of file
diff --git a/apihost/Tnb.API.Entry/Configurations/EventBus.json b/apihost/Tnb.API.Entry/Configurations/EventBus.json
new file mode 100644
index 00000000..8600f134
--- /dev/null
+++ b/apihost/Tnb.API.Entry/Configurations/EventBus.json
@@ -0,0 +1,8 @@
+{
+ "EventBus": {
+ "EventBusType": "Memory", //Memory,RabbitMQ
+ "HostName": "192.168.0.232",
+ "UserName": "jnpf",
+ "Password": "jnpf@2019"
+ }
+}
\ No newline at end of file
diff --git a/apihost/Tnb.API.Entry/Configurations/JWT.json b/apihost/Tnb.API.Entry/Configurations/JWT.json
index 10b5e739..cf2e1415 100644
--- a/apihost/Tnb.API.Entry/Configurations/JWT.json
+++ b/apihost/Tnb.API.Entry/Configurations/JWT.json
@@ -1,7 +1,7 @@
{
"JWTSettings": {
"ValidateIssuerSigningKey": true, // 是否验证密钥,bool 类型,默认true
- "IssuerSigningKey": "7k5yOxSMHVdYjs61gkgUY3W9DHbgk7tokaZlP3QIlfk34D1H7jYEOcLybClW1aKl", // 密钥,string 类型,必须是复杂密钥,长度大于16
+ "IssuerSigningKey": "RkayGi4ltkMWrSQKsQTWic1VnakqsQfaJOmJIBUWE1gxGaS0IrJHxa9anjVAwuew", // 密钥,string 类型,必须是复杂密钥,长度大于16
"ValidateIssuer": true, // 是否验证签发方,bool 类型,默认true
"ValidIssuer": "tuotong", // 签发方,string 类型
"ValidateAudience": true, // 是否验证签收方,bool 类型,默认true
diff --git a/apihost/Tnb.API.Entry/Configurations/JobConnectionStrings.json b/apihost/Tnb.API.Entry/Configurations/JobConnectionStrings.json
new file mode 100644
index 00000000..aa92ddf2
--- /dev/null
+++ b/apihost/Tnb.API.Entry/Configurations/JobConnectionStrings.json
@@ -0,0 +1,23 @@
+{
+ "JobConnectionStrings": {
+ "ConfigId": "JNPF-Job",// 不可修改
+ "DBName": "jnpf_sundial",
+ "DBType": "SqlServer", //MySql;SqlServer;Oracle;PostgreSQL;Dm;Kdbndp;Sqlite;
+ "Host": "192.168.0.214",
+ "Port": "1433",
+ "UserName": "sa",
+ "Password": "kMaeMP8Yck6b6wA",
+ //SqlServer
+ "DefaultConnection": "Data Source=192.168.0.214;Initial Catalog={0};User ID=sa;Password=kMaeMP8Yck6b6wA;MultipleActiveResultSets=true"
+ //Kdbndp
+ //"DefaultConnection": "Server=192.168.0.103;Port=54321;UID=YANYU;PWD=123456;database=YANSOURCE"
+ //Dm
+ //"DefaultConnection": "Server=192.168.0.50; User Id=JNPFTEST; PWD=I97eH!bRfy55qGzF;DATABASE=JNPFTEST"
+ //Oracle
+ //"DefaultConnection": "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.19)(PORT=1521))(CONNECT_DATA=(SERVER = DEDICATED)(SERVICE_NAME=JNPFCLOUD)));User Id=JNPFCLOUD;Password=JNPFCLOUD"
+ //PostgreSQL
+ //"DefaultConnection": "PORT=5432;DATABASE=java_boot_dev_postgresql;HOST=192.168.0.103;PASSWORD=123456;USER ID=postgres"
+ //MySql
+ //"DefaultConnection": "server=192.168.0.10;Database=netcore_test;Uid=netcore_test;Pwd=jhpGB3A88CF57fBC;AllowLoadLocalInfile=true"
+ }
+}
\ No newline at end of file
diff --git a/apihost/Tnb.API.Entry/Configurations/Swagger.json b/apihost/Tnb.API.Entry/Configurations/Swagger.json
index e6a1899c..9f45fc4e 100644
--- a/apihost/Tnb.API.Entry/Configurations/Swagger.json
+++ b/apihost/Tnb.API.Entry/Configurations/Swagger.json
@@ -8,7 +8,7 @@
"Group": "Default",
"Title": "ToTong Next Builder",
"Description": "",
- "Version": "3.4.5"
+ "Version": "3.4.6"
}
],
"LoginInfo": {
diff --git a/apihost/Tnb.API.Entry/Extensions/ConfigureEventBusExtensions.cs b/apihost/Tnb.API.Entry/Extensions/ConfigureEventBusExtensions.cs
index 180ede3a..214f6c8a 100644
--- a/apihost/Tnb.API.Entry/Extensions/ConfigureEventBusExtensions.cs
+++ b/apihost/Tnb.API.Entry/Extensions/ConfigureEventBusExtensions.cs
@@ -1,4 +1,5 @@
using JNPF;
+using JNPF.Common.Core;
using JNPF.Common.Options;
using JNPF.EventHandler;
using OnceMi.AspNetCore.OSS;
@@ -17,40 +18,53 @@ public static class ConfigureEventBusExtensions
///
public static IServiceCollection ConfigureEventBus(this IServiceCollection services)
{
- // 注册EventBus服务
- services.AddEventBus(options =>
- {
- //// 创建连接工厂
- //var factory = new RabbitMQ.Client.ConnectionFactory
- //{
- // // 设置主机名
- // HostName = "192.168.0.232",
+ // 注册EventBus服务
+ // 注册EventBus服务
+ services.AddEventBus(options =>
+ {
+ var config = App.GetOptions();
- // // 用户名
- // UserName = "jnpf",
+ if (config.EventBusType != EventBusType.Memory)
+ {
+ switch (config.EventBusType)
+ {
+ case EventBusType.RabbitMQ:
+ // 创建连接工厂
+ var factory = new RabbitMQ.Client.ConnectionFactory
+ {
+ // 设置主机名
+ HostName = config.HostName,
- // // 密码
- // Password = "jnpf@2019",
- //};
+ // 用户名
+ UserName = config.UserName,
- //// 创建默认内存通道事件源对象,可自定义队列路由key,比如这里是 eventbus
- //var rbmqEventSourceStorer = new RabbitMQEventSourceStorer(factory, "eventbus", 3000);
+ // 密码
+ Password = config.Password,
+ };
- //// 替换默认事件总线存储器
- //options.ReplaceStorer(serviceProvider =>
- //{
- // return rbmqEventSourceStorer;
- //});
+ // 创建默认内存通道事件源对象,可自定义队列路由key,比如这里是 eventbus
+ var rbmqEventSourceStorer = new RabbitMQEventSourceStorer(factory, "eventbus", 3000);
- options.UseUtcTimestamp = false;
+ // 替换默认事件总线存储器
+ options.ReplaceStorer(serviceProvider =>
+ {
+ return rbmqEventSourceStorer;
+ });
+ break;
+ }
+ }
- // 不启用事件日志
- options.LogEnabled = false;
+ options.UseUtcTimestamp = false;
- // 事件执行器(失败重试)
- options.AddExecutor();
- });
+ // 不启用事件日志
+ options.LogEnabled = false;
- return services;
+ // 事件执行器(失败重试)
+ options.AddExecutor();
+ });
+
+ services.AddConfigurableOptions();
+
+ return services;
}
}
\ No newline at end of file
diff --git a/apihost/Tnb.API.Entry/Extensions/ConfigureMvcControllerExtensions.cs b/apihost/Tnb.API.Entry/Extensions/ConfigureMvcControllerExtensions.cs
index 4dc1208b..f783c29d 100644
--- a/apihost/Tnb.API.Entry/Extensions/ConfigureMvcControllerExtensions.cs
+++ b/apihost/Tnb.API.Entry/Extensions/ConfigureMvcControllerExtensions.cs
@@ -10,6 +10,7 @@ using Newtonsoft.Json;
using OnceMi.AspNetCore.OSS;
using JNPF.API.Entry.Handlers;
using JNPF.Common.Cache;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
namespace Microsoft.Extensions.DependencyInjection;
@@ -18,60 +19,108 @@ namespace Microsoft.Extensions.DependencyInjection;
///
public static class ConfigureMvcControllerExtensions
{
- ///
- /// OSS服务配置.
- ///
- ///
- ///
- public static IServiceCollection ConfigureMvcController(this IServiceCollection services)
- {
- services.AddControllers()
- .AddMvcFilter()
- .AddInjectWithUnifyResult()
- .AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null)
- .AddNewtonsoftJson(options =>
+ ///
+ /// OSS服务配置.
+ ///
+ ///
+ ///
+ public static IServiceCollection ConfigureMvcController(this IServiceCollection services)
+ {
+ services.AddControllers()
+ .AddMvcFilter()
+ .AddInjectWithUnifyResult()
+ .AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null)
+ .AddNewtonsoftJson(options =>
+ {
+ // 默认命名规则
+ options.SerializerSettings.ContractResolver = new DefaultContractResolver();
+
+ // 设置时区为 UTC
+ options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
+
+ // 格式化json输出的日期格式
+ options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
+
+ // 忽略空值
+ // options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
+
+ // 忽略循环引用
+ options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
+
+ // 格式化json输出的日期格式为时间戳
+ options.SerializerSettings.Converters.Add(new NewtonsoftDateTimeJsonConverter());
+ });
+
+ services.AddUnifyJsonOptions("special", new JsonSerializerSettings
{
- // 默认命名规则
- options.SerializerSettings.ContractResolver = new DefaultContractResolver();
+ // 默认命名规则
+ ContractResolver = new DefaultContractResolver(),
- // 设置时区为 UTC
- options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
+ // 设置时区为 UTC
+ DateTimeZoneHandling = DateTimeZoneHandling.Utc,
- // 格式化json输出的日期格式
- options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
-
- // 忽略空值
- // options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
-
- // 忽略循环引用
- options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
-
- // 格式化json输出的日期格式为时间戳
- options.SerializerSettings.Converters.Add(new NewtonsoftDateTimeJsonConverter());
+ // 格式化json输出的日期格式
+ DateFormatString = "yyyy-MM-dd HH:mm:ss",
});
- // 配置Nginx转发获取客户端真实IP
- // 注1:如果负载均衡不是在本机通过 Loopback 地址转发请求的,一定要加上options.KnownNetworks.Clear()和options.KnownProxies.Clear()
- // 注2:如果设置环境变量 ASPNETCORE_FORWARDEDHEADERS_ENABLED 为 True,则不需要下面的配置代码
- services.Configure(options =>
- {
- options.ForwardedHeaders = ForwardedHeaders.All;
- options.KnownNetworks.Clear();
- options.KnownProxies.Clear();
- });
+ // 配置Nginx转发获取客户端真实IP
+ // 注1:如果负载均衡不是在本机通过 Loopback 地址转发请求的,一定要加上options.KnownNetworks.Clear()和options.KnownProxies.Clear()
+ // 注2:如果设置环境变量 ASPNETCORE_FORWARDEDHEADERS_ENABLED 为 True,则不需要下面的配置代码
+ services.Configure(options =>
+ {
+ options.ForwardedHeaders = ForwardedHeaders.All;
+ options.KnownNetworks.Clear();
+ options.KnownProxies.Clear();
+ });
- // Jwt处理程序
- services.AddJwt(enableGlobalAuthorize: true);
+ // Jwt处理程序
+ services.AddJwt(enableGlobalAuthorize: true, jwtBearerConfigure: options =>
+ {
+ // 实现 JWT 身份验证过程控制
+ options.Events = new JwtBearerEvents
+ {
+ // 添加读取 Token 的方式
+ OnMessageReceived = context =>
+ {
+ var httpContext = context.HttpContext;
- // 跨域
- services.AddCorsAccessor();
+ // 判断请求是否包含 token 参数,如果有就设置给 Token
+ if (httpContext.Request.Query.ContainsKey("token"))
+ {
+ // 设置 Token
+ context.Token = httpContext.Request.Query["token"];
+ }
- services.AddConfigurableOptions();
- services.AddSession();
- services.AddMemoryCache(); // 使用本地缓存必须添加
+ return Task.CompletedTask;
+ },
- services.AddSingleton();
+ // Token 验证通过处理
+ OnTokenValidated = context =>
+ {
+ return Task.CompletedTask;
+ },
+ };
+ });
- return services;
- }
+ // 跨域
+ services.AddCorsAccessor();
+
+ // 注册远程请求
+ services.AddRemoteRequest();
+
+ // 视图引擎
+ services.AddViewEngine();
+
+ // 脱敏词汇检测
+ services.AddSensitiveDetection();
+
+ // WebSocket服务
+ services.AddWebSocketManager();
+
+ services.AddSession();
+
+ services.AddSingleton();
+
+ return services;
+ }
}
\ No newline at end of file
diff --git a/apihost/Tnb.API.Entry/Extensions/ConfigureSqlSugarExtensions.cs b/apihost/Tnb.API.Entry/Extensions/ConfigureSqlSugarExtensions.cs
index 3b269846..7f7378b4 100644
--- a/apihost/Tnb.API.Entry/Extensions/ConfigureSqlSugarExtensions.cs
+++ b/apihost/Tnb.API.Entry/Extensions/ConfigureSqlSugarExtensions.cs
@@ -23,7 +23,7 @@ public static class ConfigureSqlSugarExtensions
// 默认数据库
connectConfigList.Add(new ConnectionConfig
{
- ConnectionString = string.Format(conn.DefaultConnection, conn.Host, conn.Port, conn.DBName, conn.UserName, conn.Password),
+ ConnectionString = conn.ConnectString,
DbType = DBType,
IsAutoCloseConnection = true,
ConfigId = conn.ConfigId,
@@ -62,10 +62,9 @@ public static class ConfigureSqlSugarExtensions
//};
});
});
+ services.AddUnitOfWork();
services.AddConfigurableOptions();
services.AddConfigurableOptions();
- services.AddUnitOfWork();
-
return services;
}
diff --git a/apihost/Tnb.API.Entry/Program.cs b/apihost/Tnb.API.Entry/Program.cs
index 6b43488e..5dfadd09 100644
--- a/apihost/Tnb.API.Entry/Program.cs
+++ b/apihost/Tnb.API.Entry/Program.cs
@@ -7,15 +7,15 @@ public class WebComponent : IWebComponent
{
public void Load(WebApplicationBuilder builder, ComponentContext componentContext)
{
- //// ־
+ builder.Host.UseWindowsService();
+ //// 日志过滤
//builder.Logging.AddFilter((provider, category, logLevel) =>
//{
// return !new[] { "Microsoft.Hosting", "Microsoft.AspNetCore" }.Any(u => category.StartsWith(u)) && logLevel >= LogLevel.Information;
//});
- builder.Host.UseWindowsService();
builder.WebHost.ConfigureKestrel(options =>
{
- // òҪ null
+ // 长度最好不要设置 null
options.Limits.MaxRequestBodySize = 52428800;
});
diff --git a/apihost/Tnb.API.Entry/Startup.cs b/apihost/Tnb.API.Entry/Startup.cs
index ff4902ac..f8da43b2 100644
--- a/apihost/Tnb.API.Entry/Startup.cs
+++ b/apihost/Tnb.API.Entry/Startup.cs
@@ -1,6 +1,7 @@
using IGeekFan.AspNetCore.Knife4jUI;
using JNPF.API.Entry.Handlers;
using JNPF.Common.Cache;
+using JNPF.Common.Core;
using JNPF.Common.Core.Filter;
using JNPF.Common.Core.Handlers;
using JNPF.Common.Security;
@@ -26,87 +27,88 @@ namespace JNPF.API.Entry;
public class Startup : AppStartup
{
- public void ConfigureServices(IServiceCollection services)
- {
- services.ConfigureMvcController();
-
- // SqlSugar
- //services.SqlSugarConfigure();
- services.ConfigureSqlSugar();
-
- // 注册EventBus服务
- services.ConfigureEventBus();
-
- // 注册远程请求
- services.AddRemoteRequest();
-
- // 视图引擎
- services.AddViewEngine();
-
- // 任务调度
- services.AddTaskScheduler();
-
- // 脱敏词汇检测
- services.AddSensitiveDetection();
-
- // WebSocket服务
- services.AddWebSocketManager();
-
- // 微信
- services.AddSenparcGlobalServices(App.Configuration) // Senparc.CO2NET 全局注册
- .AddSenparcWeixinServices(App.Configuration); // Senparc.Weixin 注册(如果使用Senparc.Weixin SDK则添加)
-
- services.ConfigureLogging();
- services.ConfigureOSSService();
-
- services.AddSchedule();
-
- services.AddOverideVisualDev();
- }
-
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider, IOptions senparcSetting, IOptions senparcWeixinSetting)
- {
- // 添加状态码拦截中间件
- app.UseUnifyResultStatusCodes();
-
- // app.UseHttpsRedirection(); // 强制https
- app.UseStaticFiles();
-
- #region 微信
- IRegisterService register = RegisterService.Start(senparcSetting.Value).UseSenparcGlobal();//启动 CO2NET 全局注册,必须!
- register.UseSenparcWeixin(senparcWeixinSetting.Value, senparcSetting.Value);//微信全局注册,必须!
- #endregion
-
- app.UseWebSockets();
-
- app.UseRouting();
-
- app.UseCorsAccessor();
-
- app.UseAuthentication();
- app.UseAuthorization();
-
- app.UseKnife4UI(options =>
+ public void ConfigureServices(IServiceCollection services)
{
- options.RoutePrefix = "newapi"; // 配置 Knife4UI 路由地址,现在是 /newapi
- foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())
- {
- options.SwaggerEndpoint("/" + groupInfo.RouteTemplate, groupInfo.Title);
- }
- });
+ // 注册和配置Mvc和api服务
+ services.ConfigureMvcController();
- app.UseInject(string.Empty);
+ // 注册和配置SqlSugar
+ services.ConfigureSqlSugar();
- //app.MapWebSocketManager("/api/message/websocket", serviceProvider.GetService());
- app.MapWebSocketManager("/websocket", serviceProvider.GetRequiredService());
+ // 注册EventBus服务
+ services.ConfigureEventBus();
- app.UseEndpoints(endpoints =>
+ // 注册和配置日志服务
+ services.ConfigureLogging();
+
+ // 注册和配置存储服务
+ services.ConfigureOSSService();
+
+ // 任务调度
+ //services.AddSchedule(options =>
+ //{
+ // options.AddPersistence();
+ //});
+
+ // 任务调度
+ services.AddTaskScheduler();
+
+ services.AddMemoryCache(); // 使用本地缓存必须添加
+ services.AddConfigurableOptions();
+
+ // 微信
+ services.AddSenparcGlobalServices(App.Configuration) // Senparc.CO2NET 全局注册
+ .AddSenparcWeixinServices(App.Configuration); // Senparc.Weixin 注册(如果使用Senparc.Weixin SDK则添加)
+
+ services.AddOverideVisualDev();
+ }
+
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider, IOptions senparcSetting, IOptions senparcWeixinSetting)
{
- endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
- });
+ // 添加状态码拦截中间件
+ app.UseUnifyResultStatusCodes();
- SnowflakeIdHelper.InitYitIdWorker();
+ // app.UseHttpsRedirection(); // 强制https
+ app.UseStaticFiles();
- //serviceProvider.GetRequiredService().StartTimerJob();
- }
+ #region 微信
+ IRegisterService register = RegisterService.Start(senparcSetting.Value).UseSenparcGlobal();//启动 CO2NET 全局注册,必须!
+ register.UseSenparcWeixin(senparcWeixinSetting.Value, senparcSetting.Value);//微信全局注册,必须!
+ #endregion
+
+ app.UseWebSockets();
+
+ app.UseRouting();
+
+ app.UseCorsAccessor();
+
+ app.UseAuthentication();
+ app.UseAuthorization();
+
+ // 任务调度看板
+ app.UseScheduleUI();
+
+ app.UseKnife4UI(options =>
+ {
+ options.RoutePrefix = "newapi"; // 配置 Knife4UI 路由地址,现在是 /newapi
+ foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())
+ {
+ options.SwaggerEndpoint("/" + groupInfo.RouteTemplate, groupInfo.Title);
+ }
+ });
+
+ app.UseInject(string.Empty);
+
+ //app.MapWebSocketManager("/api/message/websocket", serviceProvider.GetService());
+ app.MapWebSocketManager("/websocket", serviceProvider.GetRequiredService());
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
+ });
+
+ SnowflakeIdHelper.InitYitIdWorker();
+
+ //serviceProvider.GetRequiredService().StartTimerJob();
+ }
}
\ No newline at end of file
diff --git a/common/Tnb.CollectiveOAuth/Enums/EnumHelper/EnumExtensions.cs b/common/Tnb.CollectiveOAuth/Enums/EnumHelper/EnumExtensions.cs
index ec0ecded..0fee4d6c 100644
--- a/common/Tnb.CollectiveOAuth/Enums/EnumHelper/EnumExtensions.cs
+++ b/common/Tnb.CollectiveOAuth/Enums/EnumHelper/EnumExtensions.cs
@@ -112,7 +112,7 @@ public static class EnumExtensions
{
if (field.FieldType.IsEnum)
{
- strValue = ((int?)enumType.InvokeMember(field.Name, BindingFlags.GetField, null, null, null)).ToString();
+ strValue = ((int)enumType.InvokeMember(field.Name, BindingFlags.GetField, null, null, null)).ToString();
object[] arr = field.GetCustomAttributes(typeDescription, true);
if (arr.Length > 0)
{
diff --git a/common/Tnb.CollectiveOAuth/Tnb.CollectiveOAuth.csproj b/common/Tnb.CollectiveOAuth/Tnb.CollectiveOAuth.csproj
index 015ae7e0..8a42c1fd 100644
--- a/common/Tnb.CollectiveOAuth/Tnb.CollectiveOAuth.csproj
+++ b/common/Tnb.CollectiveOAuth/Tnb.CollectiveOAuth.csproj
@@ -11,7 +11,6 @@
-
diff --git a/common/Tnb.Common.Core/EventBus/EventBusOptions.cs b/common/Tnb.Common.Core/EventBus/EventBusOptions.cs
new file mode 100644
index 00000000..c77b2a65
--- /dev/null
+++ b/common/Tnb.Common.Core/EventBus/EventBusOptions.cs
@@ -0,0 +1,55 @@
+using JNPF.ConfigurableOptions;
+
+namespace JNPF.Common.Core;
+
+///
+/// 事件总线配置.
+///
+public class EventBusOptions : IConfigurableOptions
+{
+ ///
+ /// 事件总线类型.
+ ///
+ public EventBusType EventBusType { get; set; }
+
+ ///
+ /// 服务器地址.
+ ///
+ public string HostName { get; set; }
+
+ ///
+ /// 账号.
+ ///
+ public string UserName { get; set; }
+
+ ///
+ /// 密码.
+ ///
+ public string Password { get; set; }
+}
+
+///
+/// 事件总线自定义事件源存储器类型.
+///
+public enum EventBusType
+{
+ ///
+ /// 内存.
+ ///
+ Memory,
+
+ ///
+ /// RabbitMQ.
+ ///
+ RabbitMQ,
+
+ ///
+ /// Redis.
+ ///
+ Redis,
+
+ ///
+ /// Kafka.
+ ///
+ Kafka,
+}
\ No newline at end of file
diff --git a/common/Tnb.Common.Core/EventBus/LogEventSubscriber.cs b/common/Tnb.Common.Core/EventBus/LogEventSubscriber.cs
index 6ef1575c..a9a47d5c 100644
--- a/common/Tnb.Common.Core/EventBus/LogEventSubscriber.cs
+++ b/common/Tnb.Common.Core/EventBus/LogEventSubscriber.cs
@@ -42,7 +42,7 @@ public class LogEventSubscriber : IEventSubscriber, ISingleton
_sqlSugarClient.ChangeDatabase(log.ConnectionConfig.ConfigId);
}
- await _sqlSugarClient.Insertable(log.Entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync();
+ await _sqlSugarClient.CopyNew().Insertable(log.Entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync();
}
///
@@ -61,6 +61,6 @@ public class LogEventSubscriber : IEventSubscriber, ISingleton
_sqlSugarClient.ChangeDatabase(log.ConnectionConfig.ConfigId);
}
- await _sqlSugarClient.Insertable(log.Entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync();
+ await _sqlSugarClient.CopyNew().Insertable(log.Entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync();
}
}
\ No newline at end of file
diff --git a/common/Tnb.Common.Core/EventBus/Sources/TaskEventSource.cs b/common/Tnb.Common.Core/EventBus/Sources/TaskEventSource.cs
index c54b727c..f4217a6d 100644
--- a/common/Tnb.Common.Core/EventBus/Sources/TaskEventSource.cs
+++ b/common/Tnb.Common.Core/EventBus/Sources/TaskEventSource.cs
@@ -1,5 +1,5 @@
-using JNPF.Systems.Entitys.System;
-using JNPF.EventBus;
+using JNPF.EventBus;
+using JNPF.TaskScheduler.Entitys;
using SqlSugar;
namespace JNPF.EventHandler;
diff --git a/common/Tnb.Common.Core/EventBus/Sources/TaskLogEventSource.cs b/common/Tnb.Common.Core/EventBus/Sources/TaskLogEventSource.cs
index b0754aef..90d3c0dc 100644
--- a/common/Tnb.Common.Core/EventBus/Sources/TaskLogEventSource.cs
+++ b/common/Tnb.Common.Core/EventBus/Sources/TaskLogEventSource.cs
@@ -1,5 +1,5 @@
-using JNPF.Systems.Entitys.System;
-using JNPF.EventBus;
+using JNPF.EventBus;
+using JNPF.TaskScheduler.Entitys;
using SqlSugar;
namespace JNPF.EventHandler;
diff --git a/common/Tnb.Common.Core/EventBus/Storers/RabbitMQEventSourceStorer.cs b/common/Tnb.Common.Core/EventBus/Storers/RabbitMQEventSourceStorer.cs
index 7847fc4e..016b366e 100644
--- a/common/Tnb.Common.Core/EventBus/Storers/RabbitMQEventSourceStorer.cs
+++ b/common/Tnb.Common.Core/EventBus/Storers/RabbitMQEventSourceStorer.cs
@@ -1,4 +1,5 @@
-using JNPF.Common.Security;
+using JNPF.Common.Extension;
+using JNPF.Common.Security;
using JNPF.EventBus;
using JNPF.Logging;
using RabbitMQ.Client;
@@ -59,8 +60,6 @@ public sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable
// 创建通道
_model = _connection.CreateModel();
- string ExchangeName = "MXK_IDENTITY_MAIN_TOPIC";
-
/*
* 声明路由队列
* 队列可以重复声明,但是声明所使用的参数必须一致,否则会抛出异常
@@ -77,7 +76,7 @@ public sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable
_model.QueueDeclare(queue: routeKey, durable: false, exclusive: false, autoDelete: false, arguments: null);
// 将MaxKey 交换机绑定到 路由中
- _model.QueueBind(queue: routeKey, exchange: ExchangeName, routingKey: "#");
+ // _model.QueueBind(queue: routeKey, exchange: "MXK_IDENTITY_MAIN_TOPIC", routingKey: "#");
// 字节限制,一次接收的消息数,全局/
// 据说prefetchSize 和global这两项,rabbitmq没有实现,暂且不研究
@@ -95,6 +94,9 @@ public sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable
// 转换为 IEventSource,这里可以选择自己喜欢的序列化工具,如果自定义了 EventSource,注意属性是可读可写
var eventSource = JsonSerializer.Deserialize(stringEventSource);
+ // 判断到是单点登录服务端信息
+ if (eventSource.EventId.IsNullOrEmpty()) eventSource = new ChannelEventSource("User:Maxkey_Identity", stringEventSource);
+
Log.Information($"- 接收到消息:{eventSource.ToJsonString()}");
// 写入内存管道存储器
@@ -105,7 +107,7 @@ public sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable
};
// 启动消费者 设置为手动应答消息
- _model.BasicConsume(queue: routeKey, autoAck: true, consumer: consumer);
+ _model.BasicConsume(queue: routeKey, autoAck: false, consumer: consumer);
}
///
@@ -122,7 +124,7 @@ public sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable
throw new ArgumentNullException(nameof(eventSource));
}
- // 这里判断是否是 ChannelEventSource 或者 自定义的 EventSouce
+ // 这里判断是否是 ChannelEventSource 或者 自定义的 EventSource
if (eventSource is ChannelEventSource source)
{
// 序列化,这里可以选择自己喜欢的序列化工具
@@ -146,7 +148,8 @@ public sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable
public async ValueTask ReadAsync(CancellationToken cancellationToken)
{
// 读取一条事件源
- return await _channel.Reader.ReadAsync(cancellationToken);
+ var eventSource = await _channel.Reader.ReadAsync(cancellationToken);
+ return eventSource;
}
///
diff --git a/common/Tnb.Common.Core/EventBus/TaskEventSubscriber.cs b/common/Tnb.Common.Core/EventBus/TaskEventSubscriber.cs
index de71532f..5f0ceb4f 100644
--- a/common/Tnb.Common.Core/EventBus/TaskEventSubscriber.cs
+++ b/common/Tnb.Common.Core/EventBus/TaskEventSubscriber.cs
@@ -1,7 +1,7 @@
using JNPF.Common.Configuration;
using JNPF.DependencyInjection;
using JNPF.EventBus;
-using JNPF.Systems.Entitys.System;
+using JNPF.TaskScheduler.Entitys;
using SqlSugar;
namespace JNPF.EventHandler;
@@ -40,7 +40,7 @@ public class TaskEventSubscriber : IEventSubscriber, ISingleton
_sqlSugarClient.ChangeDatabase(log.ConnectionConfig.ConfigId);
}
- await _sqlSugarClient.Updateable().SetColumns(x => new TimeTaskEntity()
+ await _sqlSugarClient.CopyNew().Updateable().SetColumns(x => new TimeTaskEntity()
{
RunCount = x.RunCount + 1,
LastRunTime = DateTime.Now,
diff --git a/common/Tnb.Common.Core/EventBus/UserEventSubscriber.cs b/common/Tnb.Common.Core/EventBus/UserEventSubscriber.cs
index 2eee34be..ee1becc0 100644
--- a/common/Tnb.Common.Core/EventBus/UserEventSubscriber.cs
+++ b/common/Tnb.Common.Core/EventBus/UserEventSubscriber.cs
@@ -1,6 +1,7 @@
using JNPF.Common.Configuration;
using JNPF.DependencyInjection;
using JNPF.EventBus;
+using JNPF.Systems.Interfaces.Permission;
using SqlSugar;
namespace JNPF.EventHandler;
@@ -15,12 +16,20 @@ public class UserEventSubscriber : IEventSubscriber, ISingleton
///
private static SqlSugarScope? _sqlSugarClient;
+ ///
+ /// 用户服务.
+ ///
+ private readonly IUsersService _usersService;
+
///
/// 构造函数.
///
- public UserEventSubscriber(ISqlSugarClient context)
+ public UserEventSubscriber(
+ ISqlSugarClient context,
+ IUsersService usersService)
{
_sqlSugarClient = (SqlSugarScope)context;
+ _usersService = usersService;
}
///
@@ -39,7 +48,7 @@ public class UserEventSubscriber : IEventSubscriber, ISingleton
_sqlSugarClient.ChangeDatabase(log.ConnectionConfig.ConfigId);
}
- await _sqlSugarClient.Updateable(log.Entity).UpdateColumns(m => new { m.FirstLogIP, m.FirstLogTime, m.PrevLogTime, m.PrevLogIP, m.LastLogTime, m.LastLogIP, m.LogSuccessCount }).ExecuteCommandAsync();
+ await _sqlSugarClient.CopyNew().Updateable(log.Entity).UpdateColumns(m => new { m.FirstLogIP, m.FirstLogTime, m.PrevLogTime, m.PrevLogIP, m.LastLogTime, m.LastLogIP, m.LogSuccessCount }).ExecuteCommandAsync();
}
///
@@ -47,9 +56,10 @@ public class UserEventSubscriber : IEventSubscriber, ISingleton
///
///
///
- [EventSubscribe("User:maxkey_identity")]
+ [EventSubscribe("User:Maxkey_Identity")]
public async Task ReceiveUserInfo(EventHandlerExecutingContext context)
{
- var log = (UserEventSource)context.Source;
+ var log = context.Source.Payload;
+ await _usersService.Receive(log.ToString());
}
}
\ No newline at end of file
diff --git a/common/Tnb.Common.Core/Filter/LogExceptionHandler.cs b/common/Tnb.Common.Core/Filter/LogExceptionHandler.cs
index 3160111c..2c019ac4 100644
--- a/common/Tnb.Common.Core/Filter/LogExceptionHandler.cs
+++ b/common/Tnb.Common.Core/Filter/LogExceptionHandler.cs
@@ -12,7 +12,6 @@ using Microsoft.AspNetCore.Mvc.Filters;
using JNPF.Systems.Entitys.System;
using System.Security.Claims;
using SqlSugar;
-using MimeKit;
namespace JNPF.Common.Core.Filter;
@@ -21,58 +20,57 @@ namespace JNPF.Common.Core.Filter;
///
public class LogExceptionHandler : IGlobalExceptionHandler, ISingleton
{
- private readonly IEventPublisher _eventPublisher;
+ private readonly IEventPublisher _eventPublisher;
- public LogExceptionHandler(IEventPublisher eventPublisher)
- {
- _eventPublisher = eventPublisher;
- }
-
- ///
- /// 异步写入异常日记.
- ///
- ///
- ///
- public async Task OnExceptionAsync(ExceptionContext context)
- {
- var userContext = App.User;
- var httpContext = context.HttpContext;
- var httpRequest = httpContext?.Request;
- var headers = httpRequest?.Headers;
- UserAgent userAgent = new UserAgent(httpContext);
-
- if (!context.ActionDescriptor.EndpointMetadata.Any(m => m.GetType() == typeof(IgnoreLogAttribute)))
+ public LogExceptionHandler(IEventPublisher eventPublisher)
{
- ConnectionConfigOptions options = userContext?.FindFirstValue(ClaimConst.CONNECTIONCONFIG)?.ToObject();
- string userId = userContext?.FindFirstValue(ClaimConst.CLAINMUSERID);
- string userName = userContext?.FindFirstValue(ClaimConst.CLAINMREALNAME);
-
- if (!App.HttpContext.Request.Headers.ContainsKey("Authorization"))
- {
- var bearer = App.HttpContext.Request.QueryString.Value.Matches(@"[?&]token=Bearer%20([\w\.-]+)($|&)");
- if (bearer.Count() > 0)
- {
- string token = bearer.Last();
- IEnumerable claims = JWTEncryption.ReadJwtToken(token.Replace("Bearer ", string.Empty).Replace("bearer ", string.Empty))?.Claims;
- options = claims.FirstOrDefault(e => e.Type == ClaimConst.CONNECTIONCONFIG).ToObject();
- userId = claims.FirstOrDefault(e => e.Type == ClaimConst.CLAINMUSERID)?.Value;
- userName = claims.FirstOrDefault(e => e.Type == ClaimConst.CLAINMREALNAME)?.Value;
- }
- }
-
- await _eventPublisher.PublishAsync(new LogEventSource("Log:CreateExLog", options, new SysLogEntity
- {
- Id = SnowflakeIdHelper.NextId(),
- UserId = userId,
- UserName = userName,
- Category = 4,
- IPAddress = NetHelper.Ip,
- RequestURL = httpRequest.Path,
- RequestMethod = httpRequest.Method,
- Json = context.Exception.Message + "\n" + context.Exception.StackTrace + "\n" + context.Exception.TargetSite.GetParameters().ToString(),
- PlatForm = string.Format("{0}-{1}", userAgent.OS.ToString(), userAgent.RawValue),
- CreatorTime = DateTime.Now
- }));
+ _eventPublisher = eventPublisher;
+ }
+
+ ///
+ /// 异步写入异常日记.
+ ///
+ ///
+ ///
+ public async Task OnExceptionAsync(ExceptionContext context)
+ {
+ var userContext = App.User;
+ var httpContext = context.HttpContext;
+ var httpRequest = httpContext?.Request;
+ var headers = httpRequest?.Headers;
+ UserAgent userAgent = new UserAgent(httpContext);
+
+ if (!context.ActionDescriptor.EndpointMetadata.Any(m => m.GetType() == typeof(IgnoreLogAttribute)))
+ {
+ ConnectionConfigOptions options = userContext?.FindFirstValue(ClaimConst.CONNECTIONCONFIG)?.ToObject();
+ string userId = userContext?.FindFirstValue(ClaimConst.CLAINMUSERID);
+ string userName = userContext?.FindFirstValue(ClaimConst.CLAINMREALNAME);
+
+ if (!App.HttpContext.Request.Headers.ContainsKey("Authorization"))
+ {
+ string token = App.HttpContext.Request.QueryString.Value.Matches(@"[?&]token=Bearer%20([\w\.-]+)($|&)").LastOrDefault();
+ if (!string.IsNullOrEmpty(token))
+ {
+ IEnumerable claims = JWTEncryption.ReadJwtToken(token.Replace("Bearer ", string.Empty).Replace("bearer ", string.Empty))?.Claims;
+ options = claims.FirstOrDefault(e => e.Type == ClaimConst.CONNECTIONCONFIG).ToObject();
+ userId = claims.FirstOrDefault(e => e.Type == ClaimConst.CLAINMUSERID)?.Value;
+ userName = claims.FirstOrDefault(e => e.Type == ClaimConst.CLAINMREALNAME)?.Value;
+ }
+ }
+
+ await _eventPublisher.PublishAsync(new LogEventSource("Log:CreateExLog", options, new SysLogEntity
+ {
+ Id = SnowflakeIdHelper.NextId(),
+ UserId = userId,
+ UserName = userName,
+ Category = 4,
+ IPAddress = NetHelper.Ip,
+ RequestURL = httpRequest.Path,
+ RequestMethod = httpRequest.Method,
+ Json = context.Exception.Message + "\n" + context.Exception.StackTrace + "\n" + context.Exception.TargetSite.GetParameters().ToString(),
+ PlatForm = string.Format("{0}-{1}", userAgent.OS.ToString(), userAgent.RawValue),
+ CreatorTime = DateTime.Now
+ }));
+ }
}
- }
}
\ No newline at end of file
diff --git a/common/Tnb.Common.Core/Filter/RequestActionFilter.cs b/common/Tnb.Common.Core/Filter/RequestActionFilter.cs
index 9fdaa517..10cb0f5d 100644
--- a/common/Tnb.Common.Core/Filter/RequestActionFilter.cs
+++ b/common/Tnb.Common.Core/Filter/RequestActionFilter.cs
@@ -22,93 +22,92 @@ namespace JNPF.Common.Core.Filter;
///
public class RequestActionFilter : IAsyncActionFilter
{
- private readonly IEventPublisher _eventPublisher;
+ private readonly IEventPublisher _eventPublisher;
- public RequestActionFilter(IEventPublisher eventPublisher)
- {
- _eventPublisher = eventPublisher;
- }
-
- ///
- /// 请求日记写入.
- ///
- ///
- ///
- ///
- public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
- {
- var userContext = App.User;
- var httpContext = context.HttpContext;
- var httpRequest = httpContext.Request;
- UserAgent userAgent = new UserAgent(httpContext);
- var actionDes = (ControllerActionDescriptor)context.ActionDescriptor;
- var actionName = $"{actionDes.ControllerTypeInfo.FullName}.{actionDes.MethodInfo.Name}";
- var ignoreLog = actionDes.EndpointMetadata.Any(m => m.GetType() == typeof(IgnoreLogAttribute));
-
- Stopwatch sw = new Stopwatch();
- if (!ignoreLog) Log.Information("Action Starting: {0}({1})", actionName, context.ActionArguments.ToJsonString());
- sw.Start();
- var actionContext = await next();
- sw.Stop();
- // 判断是否请求成功(没有异常就是请求成功)
- var isRequestSucceed = actionContext.Exception == null;
- //var headers = httpRequest.Headers;
- if (!ignoreLog && isRequestSucceed)
+ public RequestActionFilter(IEventPublisher eventPublisher)
{
- Log.Information("Action Finished: {0}() - Elapsed: {1:F2}ms", actionName, sw.ElapsedMilliseconds);
- ConnectionConfigOptions options = userContext?.FindFirstValue(ClaimConst.CONNECTIONCONFIG)?.ToObject();
- var userId = userContext?.FindFirstValue(ClaimConst.CLAINMUSERID);
- var userName = userContext?.FindFirstValue(ClaimConst.CLAINMREALNAME);
- if (!App.HttpContext.Request.Headers.ContainsKey("Authorization"))
- {
- var bearer = App.HttpContext.Request.QueryString.Value.Matches(@"[?&]token=Bearer%20([\w\.-]+)($|&)");
- if (bearer.Count() > 0)
- {
- string token = bearer.Last();
- IEnumerable claims = JWTEncryption.ReadJwtToken(token.Replace("Bearer ", string.Empty).Replace("bearer ", string.Empty))?.Claims;
- options = claims.FirstOrDefault(e => e.Type == ClaimConst.CONNECTIONCONFIG).ToObject();
- userId = claims.FirstOrDefault(e => e.Type == ClaimConst.CLAINMUSERID)?.Value;
- userName = claims.FirstOrDefault(e => e.Type == ClaimConst.CLAINMREALNAME)?.Value;
- }
- }
-
- await _eventPublisher.PublishAsync(new LogEventSource("Log:CreateReLog", options, new SysLogEntity
- {
- Id = SnowflakeIdHelper.NextId(),
- UserId = userId,
- UserName = userName,
- Category = 5,
- IPAddress = NetHelper.Ip,
- RequestURL = httpRequest.Path,
- RequestDuration = (int)sw.ElapsedMilliseconds,
- RequestMethod = httpRequest.Method,
- PlatForm = string.Format("{0}-{1}", userAgent.OS.ToString(), userAgent.RawValue),
- CreatorTime = DateTime.Now
- }));
-
- var module = actionDes.EndpointMetadata.Where(x => x.GetType() == typeof(OperateLogAttribute)).FirstOrDefault() as OperateLogAttribute;
- if (module != null)
- {
- // 操作参数
- var args = context.ActionArguments.ToJsonString();
- var result = (actionContext.Result as JsonResult)?.Value;
-
- await _eventPublisher.PublishAsync(new LogEventSource("Log:CreateOpLog", options, new SysLogEntity
- {
- Id = SnowflakeIdHelper.NextId(),
- UserId = userId,
- UserName = userName,
- Category = 3,
- IPAddress = NetHelper.Ip,
- RequestURL = httpRequest.Path,
- RequestDuration = (int)sw.ElapsedMilliseconds,
- RequestMethod = module.Action,
- PlatForm = string.Format("{0}-{1}", userAgent.OS.ToString(), userAgent.RawValue),
- CreatorTime = DateTime.Now,
- ModuleName = module.ModuleName,
- Json = string.Format("{0}应用【{1}】【{2}】", module.Action, args, result?.ToJsonString())
- }));
- }
+ _eventPublisher = eventPublisher;
+ }
+
+ ///
+ /// 请求日记写入.
+ ///
+ ///
+ ///
+ ///
+ public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
+ {
+ var userContext = App.User;
+ var httpContext = context.HttpContext;
+ var httpRequest = httpContext.Request;
+ UserAgent userAgent = new UserAgent(httpContext);
+ var actionDes = (ControllerActionDescriptor)context.ActionDescriptor;
+ var actionName = $"{actionDes.ControllerTypeInfo.FullName}.{actionDes.MethodInfo.Name}";
+ var ignoreLog = actionDes.EndpointMetadata.Any(m => m.GetType() == typeof(IgnoreLogAttribute));
+
+ Stopwatch sw = new Stopwatch();
+ if (!ignoreLog) Log.Information("Action Starting: {0}({1})", actionName, context.ActionArguments.ToJsonString());
+ sw.Start();
+ var actionContext = await next();
+ sw.Stop();
+ // 判断是否请求成功(没有异常就是请求成功)
+ var isRequestSucceed = actionContext.Exception == null;
+ //var headers = httpRequest.Headers;
+ if (!ignoreLog && isRequestSucceed)
+ {
+ Log.Information("Action Finished: {0}() - Elapsed: {1:F2}ms", actionName, sw.ElapsedMilliseconds);
+ ConnectionConfigOptions options = userContext?.FindFirstValue(ClaimConst.CONNECTIONCONFIG)?.ToObject();
+ var userId = userContext?.FindFirstValue(ClaimConst.CLAINMUSERID);
+ var userName = userContext?.FindFirstValue(ClaimConst.CLAINMREALNAME);
+ if (!App.HttpContext.Request.Headers.ContainsKey("Authorization"))
+ {
+ var token = App.HttpContext.Request.QueryString.Value.Matches(@"[?&]token=Bearer%20([\w\.-]+)($|&)").LastOrDefault();
+ if (!string.IsNullOrEmpty(token))
+ {
+ IEnumerable claims = JWTEncryption.ReadJwtToken(token.Replace("Bearer ", string.Empty).Replace("bearer ", string.Empty))?.Claims;
+ options = claims.FirstOrDefault(e => e.Type == ClaimConst.CONNECTIONCONFIG).ToObject();
+ userId = claims.FirstOrDefault(e => e.Type == ClaimConst.CLAINMUSERID)?.Value;
+ userName = claims.FirstOrDefault(e => e.Type == ClaimConst.CLAINMREALNAME)?.Value;
+ }
+ }
+
+ await _eventPublisher.PublishAsync(new LogEventSource("Log:CreateReLog", options, new SysLogEntity
+ {
+ Id = SnowflakeIdHelper.NextId(),
+ UserId = userId,
+ UserName = userName,
+ Category = 5,
+ IPAddress = NetHelper.Ip,
+ RequestURL = httpRequest.Path,
+ RequestDuration = (int)sw.ElapsedMilliseconds,
+ RequestMethod = httpRequest.Method,
+ PlatForm = string.Format("{0}-{1}", userAgent.OS.ToString(), userAgent.RawValue),
+ CreatorTime = DateTime.Now
+ }));
+
+ var module = actionDes.EndpointMetadata.Where(x => x.GetType() == typeof(OperateLogAttribute)).FirstOrDefault() as OperateLogAttribute;
+ if (module != null)
+ {
+ // 操作参数
+ var args = context.ActionArguments.ToJsonString();
+ var result = (actionContext.Result as JsonResult)?.Value;
+
+ await _eventPublisher.PublishAsync(new LogEventSource("Log:CreateOpLog", options, new SysLogEntity
+ {
+ Id = SnowflakeIdHelper.NextId(),
+ UserId = userId,
+ UserName = userName,
+ Category = 3,
+ IPAddress = NetHelper.Ip,
+ RequestURL = httpRequest.Path,
+ RequestDuration = (int)sw.ElapsedMilliseconds,
+ RequestMethod = module.Action,
+ PlatForm = string.Format("{0}-{1}", userAgent.OS.ToString(), userAgent.RawValue),
+ CreatorTime = DateTime.Now,
+ ModuleName = module.ModuleName,
+ Json = string.Format("{0}应用【{1}】【{2}】", module.Action, args, result?.ToJsonString())
+ }));
+ }
+ }
}
- }
}
\ No newline at end of file
diff --git a/common/Tnb.Common.Core/Handlers/IMHandler.cs b/common/Tnb.Common.Core/Handlers/IMHandler.cs
index 06c30585..1e8e5bba 100644
--- a/common/Tnb.Common.Core/Handlers/IMHandler.cs
+++ b/common/Tnb.Common.Core/Handlers/IMHandler.cs
@@ -1,6 +1,4 @@
-using System.Net.Sockets;
-using System.Net.WebSockets;
-using Aop.Api.Domain;
+using System.Net.WebSockets;
using JNPF.Common.Configuration;
using JNPF.Common.Const;
using JNPF.Common.Enums;
@@ -76,6 +74,7 @@ public class IMHandler : WebSocketHandler
client.LoginIpAddress = client.LoginIpAddress;
client.Token = message.token;
client.IsMobileDevice = message.mobileDevice;
+ client.onlineTicket = claims.FirstOrDefault(e => e.Type == ClaimConst.OnlineTicket)?.Value;
if (client.WebSocket.State != WebSocketState.Open) return;
await OnConnected(client.ConnectionId, client);
WebSocketConnectionManager.AddToTenant(client.ConnectionId, client.ConnectionConfig?.ConfigId);
@@ -177,7 +176,8 @@ public class IMHandler : WebSocketHandler
tenantId = client.ConnectionConfig.ConfigId,
lastLoginPlatForm = client.LoginPlatForm,
isMobileDevice = client.IsMobileDevice,
- token = message.token
+ token = message.token,
+ onlineTicket = client.onlineTicket
});
await SetOnlineUserList(client.ConnectionConfig.ConfigId, list);
}
@@ -201,7 +201,8 @@ public class IMHandler : WebSocketHandler
tenantId = client.ConnectionConfig.ConfigId,
lastLoginPlatForm = client.LoginPlatForm,
isMobileDevice = client.IsMobileDevice,
- token = message.token
+ token = message.token,
+ onlineTicket = client.onlineTicket
});
await SetOnlineUserList(client.ConnectionConfig.ConfigId, list);
}
@@ -230,7 +231,8 @@ public class IMHandler : WebSocketHandler
tenantId = client.ConnectionConfig.ConfigId,
lastLoginPlatForm = client.LoginPlatForm,
isMobileDevice = client.IsMobileDevice,
- token = message.token
+ token = message.token,
+ onlineTicket = client.onlineTicket
});
await SetOnlineUserList(client.ConnectionConfig.ConfigId, list);
@@ -263,10 +265,11 @@ public class IMHandler : WebSocketHandler
}
var unreadNoticeCount = await _sqlSugarClient.Queryable((m, mr) => new JoinQueryInfos(JoinType.Left, m.Id == mr.MessageId)).Where((m, mr) => m.Type == 1 && m.DeleteMark == null && mr.UserId == client.UserId && mr.IsRead == 0).Select((m, mr) => new { mr.Id, mr.UserId, mr.IsRead, m.Type, m.DeleteMark }).CountAsync();
var unreadMessageCount = await _sqlSugarClient.Queryable((m, mr) => new JoinQueryInfos(JoinType.Left, m.Id == mr.MessageId)).Select((m, mr) => new { mr.Id, mr.UserId, mr.IsRead, m.Type, m.DeleteMark }).MergeTable().Where(x => x.Type == 2 && x.DeleteMark == null && x.UserId == client.UserId && x.IsRead == 0).CountAsync();
- var messageDefault = await _sqlSugarClient.Queryable().Where(x => x.DeleteMark == null && x.EnabledMark == 1).OrderBy(x => x.CreatorTime, OrderByType.Desc).FirstAsync();
+ var unreadSystemMessageCount = await _sqlSugarClient.Queryable((m, mr) => new JoinQueryInfos(JoinType.Left, m.Id == mr.MessageId)).Select((m, mr) => new { mr.Id, mr.UserId, mr.IsRead, m.Type, m.DeleteMark }).MergeTable().Where(x => x.Type == 3 && x.DeleteMark == null && x.UserId == client.UserId && x.IsRead == 0).CountAsync();
+ var messageDefault = await _sqlSugarClient.Queryable((m, mr) => new JoinQueryInfos(JoinType.Left, m.Id == mr.MessageId)).Where((m, mr) => m.DeleteMark == null && mr.UserId == client.UserId).OrderBy((m, mr) => m.LastModifyTime, OrderByType.Desc).FirstAsync();
var messageDefaultText = messageDefault == null ? string.Empty : messageDefault.Title;
var messageDefaultTime = messageDefault == null ? DateTime.Now : messageDefault.CreatorTime;
- await SendMessageAsync(client.ConnectionId, new { method = MessageSendType.initMessage.ToString(), onlineUserList, unreadNums, unreadNoticeCount, unreadMessageCount, messageDefaultText, messageDefaultTime }.ToJsonString());
+ await SendMessageAsync(client.ConnectionId, new { method = MessageSendType.initMessage.ToString(), onlineUserList, unreadNums, unreadNoticeCount, unreadMessageCount, messageDefaultText, messageDefaultTime, unreadSystemMessageCount }.ToJsonString());
await SendMessageToTenantAsync(client.ConnectionConfig.ConfigId, new { method = MessageSendType.online.ToString(), userId = client.UserId }.ToJsonString(), client.ConnectionId);
}
diff --git a/common/Tnb.Common.Core/Job/DbJobPersistence.cs b/common/Tnb.Common.Core/Job/DbJobPersistence.cs
new file mode 100644
index 00000000..e4b0d60d
--- /dev/null
+++ b/common/Tnb.Common.Core/Job/DbJobPersistence.cs
@@ -0,0 +1,199 @@
+using JNPF.Schedule;
+using JNPF.TaskScheduler.Entitys;
+using JNPF.TaskScheduler.Entitys.Enum;
+using Mapster;
+using Microsoft.Extensions.DependencyInjection;
+using SqlSugar;
+
+namespace JNPF.Common.Core;
+
+///
+/// 作业持久化(数据库).
+///
+public class DbJobPersistence : IJobPersistence
+{
+ private readonly IServiceScopeFactory _serviceScopeFactory;
+
+ public DbJobPersistence(IServiceScopeFactory serviceScopeFactory)
+ {
+ _serviceScopeFactory = serviceScopeFactory;
+ }
+
+ ///
+ /// 作业调度服务启动时.
+ ///
+ ///
+ public IEnumerable Preload()
+ {
+ using var scope = _serviceScopeFactory.CreateScope();
+ var sqlSugarClient = scope.ServiceProvider.GetRequiredService();
+
+ // 获取到对应库连接
+ var sqlSugarScope = sqlSugarClient.AsTenant().GetConnectionScopeWithAttr();
+ var dynamicJobCompiler = scope.ServiceProvider.GetRequiredService();
+
+ // 获取所有定义的作业
+ var allJobs = App.EffectiveTypes.ScanToBuilders().ToList();
+
+ //// 若数据库不存在任何作业,则直接返回
+ if (!sqlSugarScope.Queryable().Any(u => true)) return allJobs;
+
+ // 遍历所有定义的作业
+ foreach (var schedulerBuilder in allJobs)
+ {
+ // 获取作业信息构建器
+ var jobBuilder = schedulerBuilder.GetJobBuilder();
+
+ // 加载数据库数据
+ var dbDetail = sqlSugarScope.Queryable().First(u => u.JobId == jobBuilder.JobId);
+ if (dbDetail == null) continue;
+
+ // 同步数据库数据
+ jobBuilder.LoadFrom(dbDetail);
+
+ // 获取作业的所有数据库的触发器
+ var dbTriggers = sqlSugarScope.Queryable().Where(u => u.JobId == jobBuilder.JobId).ToArray();
+
+ // 遍历所有作业触发器
+ foreach (var (_, triggerBuilder) in schedulerBuilder.GetEnumerable())
+ {
+ // 加载数据库数据
+ var dbTrigger = dbTriggers.FirstOrDefault(u => u.JobId == jobBuilder.JobId && u.TriggerId == triggerBuilder.TriggerId);
+ if (dbTrigger == null) continue;
+
+ triggerBuilder.LoadFrom(dbTrigger).Updated(); // 标记更新
+ }
+
+ // 遍历所有非编译时定义的触发器加入到作业中
+ foreach (var dbTrigger in dbTriggers)
+ {
+ if (schedulerBuilder.GetTriggerBuilder(dbTrigger.TriggerId)?.JobId == jobBuilder.JobId) continue;
+ var triggerBuilder = TriggerBuilder.Create(dbTrigger.TriggerId).LoadFrom(dbTrigger);
+ schedulerBuilder.AddTriggerBuilder(triggerBuilder); // 先添加
+ triggerBuilder.Updated(); // 再标记更新
+ }
+
+ // 标记更新
+ schedulerBuilder.Updated();
+ }
+
+ // 获取数据库所有通过脚本创建的作业
+ var allDbScriptJobs = sqlSugarScope.Queryable().Where(u => u.CreateType != RequestTypeEnum.BuiltIn).ToList();
+ foreach (var dbDetail in allDbScriptJobs)
+ {
+ // 动态创建作业
+ Type jobType;
+ switch (dbDetail.CreateType)
+ {
+ case RequestTypeEnum.Script:
+ jobType = dynamicJobCompiler.BuildJob(dbDetail.ScriptCode);
+ break;
+
+ case RequestTypeEnum.Http:
+ jobType = typeof(HttpJob);
+ break;
+
+ default:
+ throw new NotSupportedException();
+ }
+
+ var jobBuilder = JobBuilder.Create(jobType).LoadFrom(dbDetail);
+
+ // 强行设置为不扫描 IJob 实现类 [Trigger] 特性触发器,否则 SchedulerBuilder.Create 会再次扫描,导致重复添加同名触发器
+ jobBuilder.SetIncludeAnnotations(false);
+
+ // 获取作业的所有数据库的触发器加入到作业中
+ var dbTriggers = sqlSugarScope.Queryable().Where(u => u.JobId == jobBuilder.JobId).ToArray();
+ var triggerBuilders = dbTriggers.Select(u => TriggerBuilder.Create(u.TriggerId).LoadFrom(u).Updated());
+ var schedulerBuilder = SchedulerBuilder.Create(jobBuilder, triggerBuilders.ToArray());
+
+ // 标记更新
+ schedulerBuilder.Updated();
+
+ allJobs.Add(schedulerBuilder);
+ }
+
+ return allJobs;
+ }
+
+ ///
+ /// 作业计划初始化通知.
+ ///
+ ///
+ ///
+ public SchedulerBuilder OnLoading(SchedulerBuilder builder)
+ {
+ return builder;
+ }
+
+ ///
+ /// 作业计划Scheduler的JobDetail变化时.
+ ///
+ ///
+ public void OnChanged(PersistenceContext context)
+ {
+ using var scope = _serviceScopeFactory.CreateScope();
+ var sqlSugarClient = scope.ServiceProvider.GetRequiredService();
+
+ // 获取到对应库连接
+ var sqlSugarScope = sqlSugarClient.AsTenant().GetConnectionScopeWithAttr();
+
+ var jobDetail = context.JobDetail.Adapt();
+
+ // 忽略记载作业组
+ var ignoreRecordingTasks = new List() { "schedule" };
+
+ if (!ignoreRecordingTasks.Contains(context.JobDetail.GroupName))
+ {
+ switch (context.Behavior)
+ {
+ case PersistenceBehavior.Appended:
+ sqlSugarScope.Insertable(jobDetail).ExecuteCommand();
+ break;
+
+ case PersistenceBehavior.Updated:
+ sqlSugarScope.Updateable(jobDetail).WhereColumns(u => new { u.JobId }).IgnoreColumns(u => new { u.Id, u.CreateType, u.ScriptCode }).ExecuteCommand();
+ break;
+
+ case PersistenceBehavior.Removed:
+ sqlSugarScope.Deleteable().Where(u => u.JobId == jobDetail.JobId).ExecuteCommand();
+ break;
+
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ }
+
+ ///
+ /// 作业计划Scheduler的触发器Trigger变化时.
+ ///
+ ///
+ public void OnTriggerChanged(PersistenceTriggerContext context)
+ {
+ using var scope = _serviceScopeFactory.CreateScope();
+ var sqlSugarClient = scope.ServiceProvider.GetRequiredService();
+
+ // 获取到对应库连接
+ var sqlSugarScope = sqlSugarClient.AsTenant().GetConnectionScopeWithAttr();
+
+ var jobTrigger = context.Trigger.Adapt();
+ switch (context.Behavior)
+ {
+ case PersistenceBehavior.Appended:
+ sqlSugarScope.Insertable(jobTrigger).ExecuteCommand();
+ break;
+
+ case PersistenceBehavior.Updated:
+ sqlSugarScope.Updateable(jobTrigger).WhereColumns(u => new { u.TriggerId, u.JobId }).IgnoreColumns(u => new { u.Id }).ExecuteCommand();
+ break;
+
+ case PersistenceBehavior.Removed:
+ sqlSugarScope.Deleteable().Where(u => u.TriggerId == jobTrigger.TriggerId && u.JobId == jobTrigger.JobId).ExecuteCommand();
+ break;
+
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/Tnb.Common.Core/Job/DynamicJobCompiler.cs b/common/Tnb.Common.Core/Job/DynamicJobCompiler.cs
new file mode 100644
index 00000000..a760ca3f
--- /dev/null
+++ b/common/Tnb.Common.Core/Job/DynamicJobCompiler.cs
@@ -0,0 +1,31 @@
+using JNPF.DependencyInjection;
+using JNPF.Schedule;
+
+namespace JNPF.Common.Core;
+
+///
+/// 动态作业编译.
+///
+public class DynamicJobCompiler : ISingleton
+{
+ ///
+ /// 编译代码并返回其中实现 IJob 的类型.
+ ///
+ /// 动态编译的作业代码
+ ///
+ public Type BuildJob(string script)
+ {
+ // 初始化
+ NatashaInitializer.Preheating();
+
+ // 动态创建作业
+ var builder = new AssemblyCSharpBuilder("JNPF.Common.Core")
+ {
+ Domain = DomainManagement.Random()
+ };
+
+ builder.Add(script);
+
+ return builder.GetAssembly().GetTypes().FirstOrDefault(u => typeof(IJob).IsAssignableFrom(u));
+ }
+}
\ No newline at end of file
diff --git a/common/Tnb.Common.Core/Manager/DataBase/DataBaseManager.cs b/common/Tnb.Common.Core/Manager/DataBase/DataBaseManager.cs
index e97480ee..2ce7223d 100644
--- a/common/Tnb.Common.Core/Manager/DataBase/DataBaseManager.cs
+++ b/common/Tnb.Common.Core/Manager/DataBase/DataBaseManager.cs
@@ -9,6 +9,7 @@ using JNPF.Common.Models;
using JNPF.Common.Models.VisualDev;
using JNPF.Common.Security;
using JNPF.DependencyInjection;
+using JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
using JNPF.FriendlyException;
using JNPF.Logging;
using JNPF.Systems.Entitys.Dto.Database;
@@ -29,7 +30,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
///
/// 初始化客户端.
///
- private static SqlSugarScope _sqlSugarClient;
+ private static SqlSugarScope? _sqlSugarClient;
///
/// 用户管理器.
@@ -41,17 +42,24 @@ public class DataBaseManager : IDataBaseManager, ITransient
///
private readonly ConnectionStringsOptions _connectionStrings;
+ ///
+ /// 多租户配置选项.
+ ///
+ private readonly TenantOptions _tenant;
+
///
/// 构造函数.
///
public DataBaseManager(
IOptions connectionOptions,
IUserManager userManager,
+ IOptions tenantOptions,
ISqlSugarClient context)
{
_sqlSugarClient = (SqlSugarScope)context;
_userManager = userManager;
_connectionStrings = connectionOptions.Value;
+ _tenant = tenantOptions.Value;
}
///
@@ -61,46 +69,66 @@ public class DataBaseManager : IDataBaseManager, ITransient
/// 切库后的SqlSugarClient.
public SqlSugarScope ChangeDataBase(DbLinkEntity link)
{
- if (_sqlSugarClient.AsTenant().IsAnyConnection(link.Id))
+ if (!"default".Equals(link.Id) && _tenant.MultiTenancyType.Equals("COLUMN"))
{
- _sqlSugarClient.ChangeDatabase(link.Id);
+ _sqlSugarClient.QueryFilter.AddTableFilter(it => it.TenantId == link.Id);
}
else
{
- _sqlSugarClient.AddConnection(new ConnectionConfig()
+ if (_sqlSugarClient.AsTenant().IsAnyConnection(link.Id))
{
- ConfigId = link.Id,
- DbType = ToDbType(link.DbType),
- ConnectionString = ToConnectionString(link),
- InitKeyType = InitKeyType.Attribute,
- IsAutoCloseConnection = true
- });
- var db = _sqlSugarClient.GetConnectionScope(link.Id);
-
- // 设置超时时间
- db.Ado.CommandTimeOut = 30;
- db.Aop.OnLogExecuted = (sql, pars) =>
+ _sqlSugarClient.ChangeDatabase(link.Id);
+ }
+ else
{
- var oldColor = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Green;
- var finalSql = UtilMethods.GetSqlString(db.CurrentConnectionConfig.DbType, sql, pars);
- Console.WriteLine($"【{DateTime.Now.ToString("HH:mm:ss.fff")}——SQL执行完成】{db.Ado.SqlExecutionTime.TotalMilliseconds} ms");
- Console.WriteLine(finalSql);
- Console.ForegroundColor = oldColor;
- if (db.Ado.SqlExecutionTime.TotalMilliseconds > 3000)
+ _sqlSugarClient.AddConnection(new ConnectionConfig()
{
- Log.Warning($"慢查询: {db.Ado.SqlExecutionTime.TotalMilliseconds}ms, SQL: " + finalSql);
+ ConfigId = link.Id,
+ DbType = ToDbType(link.DbType),
+ ConnectionString = ToConnectionString(link),
+ InitKeyType = InitKeyType.Attribute,
+ IsAutoCloseConnection = true
+ });
+
+ _sqlSugarClient.Ado.CommandTimeOut = 30;
+
+ _sqlSugarClient.Aop.OnLogExecuted = (sql, pars) =>
+ {
+ var oldColor = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Green;
+ var finalSql = UtilMethods.GetSqlString(_sqlSugarClient.CurrentConnectionConfig.DbType, sql, pars);
+ Console.WriteLine($"【{DateTime.Now.ToString("HH:mm:ss.fff")}——SQL执行完成】{_sqlSugarClient.Ado.SqlExecutionTime.TotalMilliseconds} ms");
+ Console.WriteLine(finalSql);
+ Console.ForegroundColor = oldColor;
+ if (_sqlSugarClient.Ado.SqlExecutionTime.TotalMilliseconds > 3000)
+ {
+ Log.Warning($"慢查询: {_sqlSugarClient.Ado.SqlExecutionTime.TotalMilliseconds}ms, SQL: " + finalSql);
+ }
+ Console.WriteLine();
+ };
+ _sqlSugarClient.Aop.OnError = (ex) =>
+ {
+ Log.Error(UtilMethods.GetSqlString(_sqlSugarClient.CurrentConnectionConfig.DbType, ex.Sql, (SugarParameter[])ex.Parametres));
+ };
+
+ if (_sqlSugarClient.CurrentConnectionConfig.DbType == SqlSugar.DbType.Oracle)
+ {
+ _sqlSugarClient.Aop.OnExecutingChangeSql = (sql, pars) =>
+ {
+ if (pars != null)
+ {
+ foreach (var item in pars)
+ {
+ // 如果是DbTppe=string设置成OracleDbType.Nvarchar2
+ item.IsNvarchar2 = true;
+ }
+ };
+ return new KeyValuePair(sql, pars);
+ };
}
- Console.WriteLine();
- };
- db.Aop.OnError = (ex) =>
- {
- Log.Error(UtilMethods.GetSqlString(db.CurrentConnectionConfig.DbType, ex.Sql, (SugarParameter[])ex.Parametres));
- };
-
- _sqlSugarClient.ChangeDatabase(link.Id);
+ _sqlSugarClient.ChangeDatabase(link.Id);
+ }
}
-
return _sqlSugarClient;
}
@@ -141,6 +169,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
else
flag = await _sqlSugarClient.Ado.ExecuteCommandAsync(strSql);
+ _sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
return flag;
}
@@ -155,7 +184,9 @@ public class DataBaseManager : IDataBaseManager, ITransient
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
_sqlSugarClient = ChangeDataBase(link);
- return _sqlSugarClient.Ado.SqlQuery(strSql).Count > 0;
+ var data = _sqlSugarClient.Ado.SqlQuery(strSql).Count > 0;
+ _sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
+ return data;
}
///
@@ -180,6 +211,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
{
foreach (var item in dicList) flag = await _sqlSugarClient.Updateable(item).AS(table).WhereColumns(primaryField).ExecuteCommandAsync();
}
+ _sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
return flag;
}
@@ -200,6 +232,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
if (string.IsNullOrEmpty(primaryField))
flag = await _sqlSugarClient.Insertable(dicList).AS(table).ExecuteReturnIdentityAsync();
+ _sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
return flag;
}
@@ -215,6 +248,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
_sqlSugarClient = ChangeDataBase(link);
CreateTable(tableModel, tableFieldList);
+ _sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
return true;
}
@@ -239,6 +273,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
}
//if (_sqlSugarClient.CurrentConnectionConfig.DbType == SqlSugar.DbType.MySql)
// AddColumnMySql(tableName, tableFieldList);
+ _sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
}
catch (Exception ex)
{
@@ -260,6 +295,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
try
{
_sqlSugarClient.DbMaintenance.DropTable(table);
+ _sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
return true;
}
catch (Exception)
@@ -284,6 +320,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
try
{
CreateTable(tableModel, tableFieldList);
+ _sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
}
catch (Exception ex)
{
@@ -309,15 +346,18 @@ public class DataBaseManager : IDataBaseManager, ITransient
var sidx = pageInput.sidx.IsNotEmptyOrNull() && pageInput.sort.IsNotEmptyOrNull(); // 按前端参数排序
var defaultSidx = columnDesign.defaultSidx.IsNotEmptyOrNull() && columnDesign.sort.IsNotEmptyOrNull(); // 按模板默认排序
+ var dataRuleJson = new List();
+ if (pageInput.dataRuleJson.IsNotEmptyOrNull()) dataRuleJson = _sqlSugarClient.Utilities.JsonToConditionalModels(pageInput.dataRuleJson);
+
var querJson = new List();
if (pageInput.queryJson.IsNotEmptyOrNull()) querJson = _sqlSugarClient.Utilities.JsonToConditionalModels(pageInput.queryJson);
var superQueryJson = new List();
if (pageInput.superQueryJson.IsNotEmptyOrNull()) superQueryJson = _sqlSugarClient.Utilities.JsonToConditionalModels(pageInput.superQueryJson);
// var sql = _sqlSugarClient.SqlQueryable
public IFormFile file { get; set; }
+
+ ///
+ /// 路径类型 defaultPath(默认路径) selfPath(自定义路径).
+ ///
+ public string pathType { get; set; } = "defaultPath";
+
+ ///
+ /// 是否用户存储(0否1是).
+ ///
+ public string isAccount { get; set; } = "0";
+
+ ///
+ /// 自定义文件夹路径.
+ ///
+ public string folder { get; set; }
}
diff --git a/common/Tnb.Common/Models/FileControlsModel.cs b/common/Tnb.Common/Models/FileControlsModel.cs
index cdf11305..b667fffd 100644
--- a/common/Tnb.Common/Models/FileControlsModel.cs
+++ b/common/Tnb.Common/Models/FileControlsModel.cs
@@ -32,4 +32,9 @@ public class FileControlsModel
/// 文件后缀.
///
public string? fileExtension { get; set; }
+
+ ///
+ /// 文件名称.
+ ///
+ public string? fileName { get; set; }
}
\ No newline at end of file
diff --git a/common/Tnb.Common/Models/NPOI/ExcelColumnModel.cs b/common/Tnb.Common/Models/NPOI/ExcelColumnModel.cs
index afb658ca..394a2a52 100644
--- a/common/Tnb.Common/Models/NPOI/ExcelColumnModel.cs
+++ b/common/Tnb.Common/Models/NPOI/ExcelColumnModel.cs
@@ -6,7 +6,8 @@ namespace JNPF.Common.Models.NPOI;
///
/// Excel导出列名
/// 版 本:V3.0.0
-/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
+/// 版 权:引迈信息技术有限公司(https://www.jnpfsoft.com)
+/// 作 者:JNPF开发平台组
/// 日 期:2017.03.09.
///
[SuppressSniffer]
diff --git a/common/Tnb.Common/Models/NPOI/ExcelConfig.cs b/common/Tnb.Common/Models/NPOI/ExcelConfig.cs
index 6da01730..8f215a02 100644
--- a/common/Tnb.Common/Models/NPOI/ExcelConfig.cs
+++ b/common/Tnb.Common/Models/NPOI/ExcelConfig.cs
@@ -6,7 +6,8 @@ namespace JNPF.Common.Models.NPOI;
///
/// Excel导出配置
/// 版 本:V3.0.0
-/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
+/// 版 权:引迈信息技术有限公司(https://www.jnpfsoft.com)
+/// 作 者:JNPF开发平台组
/// 日 期:2017.03.09.
///
[SuppressSniffer]
diff --git a/common/Tnb.Common/Models/NPOI/ExcelTemplateModel.cs b/common/Tnb.Common/Models/NPOI/ExcelTemplateModel.cs
index 357a4e01..ce795303 100644
--- a/common/Tnb.Common/Models/NPOI/ExcelTemplateModel.cs
+++ b/common/Tnb.Common/Models/NPOI/ExcelTemplateModel.cs
@@ -5,7 +5,8 @@ namespace JNPF.Common.Models.NPOI;
///
/// Excel导出模板
/// 版 本:V3.0.0
-/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
+/// 版 权:引迈信息技术有限公司(https://www.jnpfsoft.com)
+/// 作 者:JNPF开发平台组
/// 日 期:2017.03.09.
///
[SuppressSniffer]
diff --git a/common/Tnb.Common/Models/User/UserInfoModel.cs b/common/Tnb.Common/Models/User/UserInfoModel.cs
index 9299aa6d..909727f7 100644
--- a/common/Tnb.Common/Models/User/UserInfoModel.cs
+++ b/common/Tnb.Common/Models/User/UserInfoModel.cs
@@ -5,7 +5,7 @@ namespace JNPF.Common.Models.User
///
/// 登录者信息
/// 版 本:V3.2.0
- /// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
+ /// 版 权:引迈信息技术有限公司(https://www.jnpfsoft.com)
/// 作 者:JNPF开发平台组.
///
[SuppressSniffer]
@@ -51,6 +51,11 @@ namespace JNPF.Common.Models.User
///
public string organizeId { get; set; }
+ ///
+ /// 所属组织 Id 树.
+ ///
+ public List organizeIdList { get; set; }
+
///
/// 组织名称.
///
@@ -225,6 +230,11 @@ namespace JNPF.Common.Models.User
///
public string signImg { get; set; }
+ ///
+ /// 默认签名.
+ ///
+ public DateTime? changePasswordDate { get; set; }
+
///
/// 系统集合.
///
diff --git a/common/Tnb.Common/Models/User/UserOnlineModel.cs b/common/Tnb.Common/Models/User/UserOnlineModel.cs
index dd96d3c6..65ba4e0b 100644
--- a/common/Tnb.Common/Models/User/UserOnlineModel.cs
+++ b/common/Tnb.Common/Models/User/UserOnlineModel.cs
@@ -53,6 +53,11 @@ public class UserOnlineModel
///
public string token { get; set; }
+ ///
+ /// 单点登录标识.
+ ///
+ public string onlineTicket { get; set; }
+
///
/// 是否移动端.
///
diff --git a/common/Tnb.Common/Models/WorkFlow/FlowJsonModel.cs b/common/Tnb.Common/Models/WorkFlow/FlowJsonModel.cs
index c3fb5a7d..cd00df37 100644
--- a/common/Tnb.Common/Models/WorkFlow/FlowJsonModel.cs
+++ b/common/Tnb.Common/Models/WorkFlow/FlowJsonModel.cs
@@ -46,5 +46,10 @@
/// 流程类型.
///
public int? type { get; set; }
+
+ ///
+ /// 所属流程名称.
+ ///
+ public string? flowName { get; set; }
}
}
diff --git a/common/Tnb.Common/Options/OauthOptions.cs b/common/Tnb.Common/Options/OauthOptions.cs
new file mode 100644
index 00000000..c6017eb2
--- /dev/null
+++ b/common/Tnb.Common/Options/OauthOptions.cs
@@ -0,0 +1,103 @@
+using Aspose.Cells;
+using JNPF.Common.Enums;
+using JNPF.ConfigurableOptions;
+using NPOI.SS.Formula.Functions;
+
+namespace JNPF.Common.Options;
+
+///
+/// 单点登录配置.
+///
+public sealed class OauthOptions : IConfigurableOptions
+{
+ ///
+ /// 是否启用.
+ ///
+ public bool Enabled { get; set; }
+
+ ///
+ /// 前端登录页面访问登录接口进行单点登录页面跳转, 需要与身份管理系统中的 JNPF-Auth2、JNPF-CAS中的认证地址一致.
+ ///
+ public string LoginPath { get; set; }
+
+ ///
+ /// 从单点登录中心直接访问JNPF时登录成功后跳转的前端页面.
+ ///
+ public string SucessFrontUrl { get; set; }
+
+ ///
+ /// 默认接口.
+ ///
+ public string DefaultSSO { get; set; }
+
+ ///
+ /// 缓存过期时间 / 分钟.
+ ///
+ public int TicketTimeout { get; set; }
+
+ ///
+ /// 是否前端输出消息.
+ ///
+ public bool TicketOutMessage { get; set; }
+
+ ///
+ /// 登录模式.
+ ///
+ public SSO SSO { get; set; }
+
+ ///
+ /// 用户推送.
+ ///
+ public Pull Pull { get; set; }
+}
+
+public class SSO
+{
+ public Auth2 Auth2 { get; set; }
+
+ public Cas Cas { get; set; }
+}
+
+public class Auth2
+{
+ public bool Enabled { get; set; }
+
+ public string ClientId { get; set; }
+
+ public string ClientSecret { get; set; }
+
+ public string AuthorizeUrl { get; set; }
+
+ public string AccessTokenUrl { get; set; }
+
+ public string UserInfoUrl { get; set; }
+}
+
+public class Cas
+{
+ public bool Enabled { get; set; }
+
+ public string ServerLoginUrl { get; set; }
+
+ public string ServerValidateUrl { get; set; }
+}
+
+public class Pull
+{
+ public bool Enabled { get; set; }
+
+ public string CreateRestAddress { get; set; }
+
+ public string ReplaceRestAddress { get; set; }
+
+ public string ChangePasswordRestAddress { get; set; }
+
+ public string DeleteRestAddress { get; set; }
+
+ public string CredentialType { get; set; }
+
+ public string UserName { get; set; }
+
+ public string Password { get; set; }
+
+}
\ No newline at end of file
diff --git a/common/Tnb.Common/Security/CodeGenExportDataHelper.cs b/common/Tnb.Common/Security/CodeGenExportDataHelper.cs
index 11141240..61b8e36a 100644
--- a/common/Tnb.Common/Security/CodeGenExportDataHelper.cs
+++ b/common/Tnb.Common/Security/CodeGenExportDataHelper.cs
@@ -54,7 +54,7 @@ public static class CodeGenExportDataHelper
var len = rowChildDatas.Select(x => x.Value.Count()).OrderByDescending(x => x).FirstOrDefault();
- if (len > 0)
+ if (len != null && len > 0)
{
for (int i = 0; i < len; i++)
{
diff --git a/common/Tnb.Common/Security/CodeGenHelper.cs b/common/Tnb.Common/Security/CodeGenHelper.cs
index 5bf8591d..aa75e88c 100644
--- a/common/Tnb.Common/Security/CodeGenHelper.cs
+++ b/common/Tnb.Common/Security/CodeGenHelper.cs
@@ -160,6 +160,79 @@ public static class CodeGenHelper
}
}
+ ///
+ /// 数据列表生成树形表格.
+ ///
+ /// 数据列表.
+ /// 树形父级字段.
+ /// 树形显示字段.
+ ///
+ public static List> GetTreeList(List> realList, string parentField, string treeShowField)
+ {
+ var res = new List>();
+ if (realList.Any())
+ {
+ var parentFieldId = SnowflakeIdHelper.NextId();
+
+ foreach (var item in realList)
+ {
+ if (realList.Any(x => x["id"].Equals(item[parentField]))) item[parentFieldId] = item[parentField];
+ else item[parentFieldId] = null;
+ item[parentField] = realList.Find(x => x["id"] == item["id"])[treeShowField];
+ }
+ var parentFieldRep = parentField.Substring(0, parentField.Length - 4);
+ for (int i = 0; i < realList.Count; i++)
+ {
+ if (realList[i][parentFieldId].IsNullOrEmpty())
+ {
+ if (realList[i][parentFieldRep] == null) realList[i][parentFieldRep] = realList[i][treeShowField];
+ var childList = realList.Where(x => x[parentFieldId] != null && x[parentFieldId].Equals(realList[i]["id"])).ToList();
+ if (childList.Any()) GetTreeList(realList, realList[i], parentFieldId);
+ res.Add(realList[i]);
+ }
+ }
+ }
+ return res;
+ }
+
+ private static void GetTreeList(List> allList, Dictionary currentItem, string pId)
+ {
+ var childList = allList.Where(x => x[pId] != null && x[pId].Equals(currentItem["id"])).ToList();
+ if (childList.Any()) childList.ForEach(x => GetTreeList(allList, x, pId));
+ if (childList.Any())
+ {
+ var item = allList.Find(x => x["id"].Equals(currentItem["id"]));
+ item["children"] = childList;
+ }
+ }
+
+ ///
+ /// 根据集合捞取所有子集id.
+ ///
+ /// key : 主键Id , value : 父亲Id.
+ /// 当前id.
+ /// res.
+ public static List GetChildIdList(Dictionary allList, string currentId, List resList)
+ {
+ if (resList == null) resList = new List() { currentId };
+ else resList.Add(currentId);
+ if (allList.Any())
+ {
+ var cItemList = allList.Where(x => x.Value.IsNotEmptyOrNull() && x.Value.Equals(currentId)).ToList();
+ if (cItemList.Any())
+ {
+ foreach (var item in cItemList)
+ {
+ var cIdList = GetChildIdList(allList, item.Key, resList);
+ resList.Add(item.Key);
+ if (cIdList.Any()) resList.AddRange(cIdList);
+ }
+ }
+ }
+
+ return resList;
+ }
+
///
/// 获取排序真实字段.
///
@@ -190,7 +263,7 @@ public static class CodeGenHelper
field = entityInfo.Columns.Find(it => it.PropertyName.Equals(sort.ToUpperCase()))?.DbColumnName;
break;
}
- return string.IsNullOrEmpty(field) ? "" : field;
+ return string.IsNullOrEmpty(field) ? null : field;
}
///
diff --git a/common/Tnb.Common/Security/ExcelExportHelper.cs b/common/Tnb.Common/Security/ExcelExportHelper.cs
index 0a34dfe4..4c3c7fa2 100644
--- a/common/Tnb.Common/Security/ExcelExportHelper.cs
+++ b/common/Tnb.Common/Security/ExcelExportHelper.cs
@@ -1,7 +1,6 @@
using System.Drawing;
using System.Reflection;
using System.Text;
-using JNPF.Common.Helper;
using JNPF.Common.Models.NPOI;
using JNPF.DependencyInjection;
using NPOI.HPSF;
@@ -9,8 +8,6 @@ using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
-using Spire.Doc;
-using static Microsoft.AspNetCore.Razor.Language.TagHelperMetadata;
namespace JNPF.Common.Security;
diff --git a/common/Tnb.Common/Security/JsonHelper.cs b/common/Tnb.Common/Security/JsonHelper.cs
index 0128eecc..dc9f8913 100644
--- a/common/Tnb.Common/Security/JsonHelper.cs
+++ b/common/Tnb.Common/Security/JsonHelper.cs
@@ -49,6 +49,17 @@ public static class JsonHelper
return _jsonSerializer.Deserialize(json);
}
+ ///
+ /// JSON 字符串转 Object.
+ ///
+ /// 动态类型.
+ /// 对象.
+ ///
+ public static T ToObjectOld(this string json)
+ {
+ return _ = JsonConvert.DeserializeObject(json) ?? default(T);
+ }
+
///
/// JSON 字符串转 Object.
///
diff --git a/common/Tnb.Common/Security/NetHelper.cs b/common/Tnb.Common/Security/NetHelper.cs
index 90e0c2aa..6424734f 100644
--- a/common/Tnb.Common/Security/NetHelper.cs
+++ b/common/Tnb.Common/Security/NetHelper.cs
@@ -28,7 +28,9 @@ public static class NetHelper
string result = string.Empty;
if (App.HttpContext != null)
result = GetWebClientIp();
- return result.Equals("::1") ? "127.0.0.1" : result;
+ result = result.Equals("::1") ? "127.0.0.1" : result;
+ result = result.Replace(":", string.Empty).Replace("ffff", string.Empty);
+ return result;
}
}
diff --git a/common/Tnb.Common/Security/PinyinHelper.cs b/common/Tnb.Common/Security/PinyinHelper.cs
index cc19afef..fe4ea1c5 100644
--- a/common/Tnb.Common/Security/PinyinHelper.cs
+++ b/common/Tnb.Common/Security/PinyinHelper.cs
@@ -12,101 +12,101 @@ namespace JNPF.Common.Security;
[SuppressSniffer]
public class PinyinHelper
{
- #region 获取汉字转换拼音 首字母
+ #region 获取汉字转换拼音 首字母
- ///
- /// 获取汉字转换拼音 首字母.
- ///
- /// 汉字字符串
- ///
- public static string PinyinString(string HanZiStr)
- {
- int i, j, k, m;
- string tmpStr;
-
- // 返回最终结果的字符串
- string returnStr = string.Empty;
- string[] tmpArr;
- for (i = 0; i < HanZiStr.Length; i++)
+ ///
+ /// 获取汉字转换拼音 首字母.
+ ///
+ /// 汉字字符串
+ ///
+ public static string PinyinString(string HanZiStr)
{
- // 处理汉字字符串,对每个汉字的首字母进行一次循环
- tmpStr = GetPinyin((char)HanZiStr[i]);
+ int i, j, k, m;
+ string tmpStr;
- // 获取第i个汉字的拼音首字母,可能为1个或多个
- if (tmpStr.Length > 0)
- {
- // 汉字的拼音首字母存在的情况才进行操作
- if (returnStr != string.Empty)
+ // 返回最终结果的字符串
+ string returnStr = string.Empty;
+ string[] tmpArr;
+ for (i = 0; i < HanZiStr.Length; i++)
{
- // 不是第一个汉字
- Regex regex = new Regex(",");
- tmpArr = regex.Split(returnStr);
- returnStr = string.Empty;
- for (k = 0; k < tmpArr.Length; k++)
- {
- // 对返回的每个首字母进行拼接
- for (j = 0; j < tmpStr.Length; j++)
- {
- // 取出第j个拼音字母
- string charcode = tmpStr[j].ToString();
- returnStr += tmpArr[k] + charcode + ",";
- }
- }
+ // 处理汉字字符串,对每个汉字的首字母进行一次循环
+ tmpStr = GetPinyin((char)HanZiStr[i]);
- if (returnStr != string.Empty)
- returnStr = returnStr.Substring(0, returnStr.Length - 1);
+ // 获取第i个汉字的拼音首字母,可能为1个或多个
+ if (tmpStr.Length > 0)
+ {
+ // 汉字的拼音首字母存在的情况才进行操作
+ if (returnStr != string.Empty)
+ {
+ // 不是第一个汉字
+ Regex regex = new Regex(",");
+ tmpArr = regex.Split(returnStr);
+ returnStr = string.Empty;
+ for (k = 0; k < tmpArr.Length; k++)
+ {
+ // 对返回的每个首字母进行拼接
+ for (j = 0; j < tmpStr.Length; j++)
+ {
+ // 取出第j个拼音字母
+ string charcode = tmpStr[j].ToString();
+ returnStr += tmpArr[k] + charcode + ",";
+ }
+ }
+
+ if (returnStr != string.Empty)
+ returnStr = returnStr.Substring(0, returnStr.Length - 1);
+ }
+ else
+ {
+ // 构造第一个汉字返回结果
+ for (m = 0; m < tmpStr.Length - 1; m++)
+ returnStr += tmpStr[m] + ",";
+ returnStr += tmpStr[tmpStr.Length - 1];
+ }
+ }
+ }
+
+ // 返回处理结果字符串,以,分隔每个拼音组合
+ return returnStr;
+ }
+
+ private static string GetPinyin(char HanZi)
+
+ // 获取单个汉字对应的拼音首字符字符串
+ {
+ // 汉字拼音首字母列表 本列表包含了20902个汉字,收录的字符的Unicode编码范围为19968至40869
+
+ string strChineseFirstPY = "YDYQSXMWZSSXJBYMGCCZQPSSQBYCDSCDQLDYLYBSSJGYZZJJFKCCLZDHWDWZJLJPFYYNWJJTMYHZWZHFLZPPQHGSCYYYNJQYXXGJHHSDSJNKKTMOMLCRXYPSNQSECCQZGGLLYJLMYZZSECYKYYHQWJSSGGYXYZYJWWKDJHYCHMYXJTLXJYQBYXZLDWRDJRWYSRLDZJPCBZJJBRCFTLECZSTZFXXZHTRQHYBDLYCZSSYMMRFMYQZPWWJJYFCRWFDFZQPYDDWYXKYJAWJFFXYPSFTZYHHYZYSWCJYXSCLCXXWZZXNBGNNXBXLZSZSBSGPYSYZDHMDZBQBZCWDZZYYTZHBTSYYBZGNTNXQYWQSKBPHHLXGYBFMJEBJHHGQTJCYSXSTKZHLYCKGLYSMZXYALMELDCCXGZYRJXSDLTYZCQKCNNJWHJTZZCQLJSTSTBNXBTYXCEQXGKWJYFLZQLYHYXSPSFXLMPBYSXXXYDJCZYLLLSJXFHJXPJBTFFYABYXBHZZBJYZLWLCZGGBTSSMDTJZXPTHYQTGLJSCQFZKJZJQNLZWLSLHDZBWJNCJZYZSQQYCQYRZCJJWYBRTWPYFTWEXCSKDZCTBZHYZZYYJXZCFFZZMJYXXSDZZOTTBZLQWFCKSZSXFYRLNYJMBDTHJXSQQCCSBXYYTSYFBXDZTGBCNSLCYZZPSAZYZZSCJCSHZQYDXLBPJLLMQXTYDZXSQJTZPXLCGLQTZWJBHCTSYJSFXYEJJTLBGXSXJMYJQQPFZASYJNTYDJXKJCDJSZCBARTDCLYJQMWNQNCLLLKBYBZZSYHQQLTWLCCXTXLLZNTYLNEWYZYXCZXXGRKRMTCNDNJTSYYSSDQDGHSDBJGHRWRQLYBGLXHLGTGXBQJDZPYJSJYJCTMRNYMGRZJCZGJMZMGXMPRYXKJNYMSGMZJYMKMFXMLDTGFBHCJHKYLPFMDXLQJJSMTQGZSJLQDLDGJYCALCMZCSDJLLNXDJFFFFJCZFMZFFPFKHKGDPSXKTACJDHHZDDCRRCFQYJKQCCWJDXHWJLYLLZGCFCQDSMLZPBJJPLSBCJGGDCKKDEZSQCCKJGCGKDJTJDLZYCXKLQSCGJCLTFPCQCZGWPJDQYZJJBYJHSJDZWGFSJGZKQCCZLLPSPKJGQJHZZLJPLGJGJJTHJJYJZCZMLZLYQBGJWMLJKXZDZNJQSYZMLJLLJKYWXMKJLHSKJGBMCLYYMKXJQLBMLLKMDXXKWYXYSLMLPSJQQJQXYXFJTJDXMXXLLCXQBSYJBGWYMBGGBCYXPJYGPEPFGDJGBHBNSQJYZJKJKHXQFGQZKFHYGKHDKLLSDJQXPQYKYBNQSXQNSZSWHBSXWHXWBZZXDMNSJBSBKBBZKLYLXGWXDRWYQZMYWSJQLCJXXJXKJEQXSCYETLZHLYYYSDZPAQYZCMTLSHTZCFYZYXYLJSDCJQAGYSLCQLYYYSHMRQQKLDXZSCSSSYDYCJYSFSJBFRSSZQSBXXPXJYSDRCKGJLGDKZJZBDKTCSYQPYHSTCLDJDHMXMCGXYZHJDDTMHLTXZXYLYMOHYJCLTYFBQQXPFBDFHHTKSQHZYYWCNXXCRWHOWGYJLEGWDQCWGFJYCSNTMYTOLBYGWQWESJPWNMLRYDZSZTXYQPZGCWXHNGPYXSHMYQJXZTDPPBFYHZHTJYFDZWKGKZBLDNTSXHQEEGZZYLZMMZYJZGXZXKHKSTXNXXWYLYAPSTHXDWHZYMPXAGKYDXBHNHXKDPJNMYHYLPMGOCSLNZHKXXLPZZLBMLSFBHHGYGYYGGBHSCYAQTYWLXTZQCEZYDQDQMMHTKLLSZHLSJZWFYHQSWSCWLQAZYNYTLSXTHAZNKZZSZZLAXXZWWCTGQQTDDYZTCCHYQZFLXPSLZYGPZSZNGLNDQTBDLXGTCTAJDKYWNSYZLJHHZZCWNYYZYWMHYCHHYXHJKZWSXHZYXLYSKQYSPSLYZWMYPPKBYGLKZHTYXAXQSYSHXASMCHKDSCRSWJPWXSGZJLWWSCHSJHSQNHCSEGNDAQTBAALZZMSSTDQJCJKTSCJAXPLGGXHHGXXZCXPDMMHLDGTYBYSJMXHMRCPXXJZCKZXSHMLQXXTTHXWZFKHCCZDYTCJYXQHLXDHYPJQXYLSYYDZOZJNYXQEZYSQYAYXWYPDGXDDXSPPYZNDLTWRHXYDXZZJHTCXMCZLHPYYYYMHZLLHNXMYLLLMDCPPXHMXDKYCYRDLTXJCHHZZXZLCCLYLNZSHZJZZLNNRLWHYQSNJHXYNTTTKYJPYCHHYEGKCTTWLGQRLGGTGTYGYHPYHYLQYQGCWYQKPYYYTTTTLHYHLLTYTTSPLKYZXGZWGPYDSSZZDQXSKCQNMJJZZBXYQMJRTFFBTKHZKBXLJJKDXJTLBWFZPPTKQTZTGPDGNTPJYFALQMKGXBDCLZFHZCLLLLADPMXDJHLCCLGYHDZFGYDDGCYYFGYDXKSSEBDHYKDKDKHNAXXYBPBYYHXZQGAFFQYJXDMLJCSQZLLPCHBSXGJYNDYBYQSPZWJLZKSDDTACTBXZDYZYPJZQSJNKKTKNJDJGYYPGTLFYQKASDNTCYHBLWDZHBBYDWJRYGKZYHEYYFJMSDTYFZJJHGCXPLXHLDWXXJKYTCYKSSSMTWCTTQZLPBSZDZWZXGZAGYKTYWXLHLSPBCLLOQMMZSSLCMBJCSZZKYDCZJGQQDSMCYTZQQLWZQZXSSFPTTFQMDDZDSHDTDWFHTDYZJYQJQKYPBDJYYXTLJHDRQXXXHAYDHRJLKLYTWHLLRLLRCXYLBWSRSZZSYMKZZHHKYHXKSMDSYDYCJPBZBSQLFCXXXNXKXWYWSDZYQOGGQMMYHCDZTTFJYYBGSTTTYBYKJDHKYXBELHTYPJQNFXFDYKZHQKZBYJTZBXHFDXKDASWTAWAJLDYJSFHBLDNNTNQJTJNCHXFJSRFWHZFMDRYJYJWZPDJKZYJYMPCYZNYNXFBYTFYFWYGDBNZZZDNYTXZEMMQBSQEHXFZMBMFLZZSRXYMJGSXWZJSPRYDJSJGXHJJGLJJYNZZJXHGXKYMLPYYYCXYTWQZSWHWLYRJLPXSLSXMFSWWKLCTNXNYNPSJSZHDZEPTXMYYWXYYSYWLXJQZQXZDCLEEELMCPJPCLWBXSQHFWWTFFJTNQJHJQDXHWLBYZNFJLALKYYJLDXHHYCSTYYWNRJYXYWTRMDRQHWQCMFJDYZMHMYYXJWMYZQZXTLMRSPWWCHAQBXYGZYPXYYRRCLMPYMGKSJSZYSRMYJSNXTPLNBAPPYPYLXYYZKYNLDZYJZCZNNLMZHHARQMPGWQTZMXXMLLHGDZXYHXKYXYCJMFFYYHJFSBSSQLXXNDYCANNMTCJCYPRRNYTYQNYYMBMSXNDLYLYSLJRLXYSXQMLLYZLZJJJKYZZCSFBZXXMSTBJGNXYZHLXNMCWSCYZYFZLXBRNNNYLBNRTGZQYSATSWRYHYJZMZDHZGZDWYBSSCSKXSYHYTXXGCQGXZZSHYXJSCRHMKKBXCZJYJYMKQHZJFNBHMQHYSNJNZYBKNQMCLGQHWLZNZSWXKHLJHYYBQLBFCDSXDLDSPFZPSKJYZWZXZDDXJSMMEGJSCSSMGCLXXKYYYLNYPWWWGYDKZJGGGZGGSYCKNJWNJPCXBJJTQTJWDSSPJXZXNZXUMELPXFSXTLLXCLJXJJLJZXCTPSWXLYDHLYQRWHSYCSQYYBYAYWJJJQFWQCQQCJQGXALDBZZYJGKGXPLTZYFXJLTPADKYQHPMATLCPDCKBMTXYBHKLENXDLEEGQDYMSAWHZMLJTWYGXLYQZLJEEYYBQQFFNLYXRDSCTGJGXYYNKLLYQKCCTLHJLQMKKZGCYYGLLLJDZGYDHZWXPYSJBZKDZGYZZHYWYFQYTYZSZYEZZLYMHJJHTSMQWYZLKYYWZCSRKQYTLTDXWCTYJKLWSQZWBDCQYNCJSRSZJLKCDCDTLZZZACQQZZDDXYPLXZBQJYLZLLLQDDZQJYJYJZYXNYYYNYJXKXDAZWYRDLJYYYRJLXLLDYXJCYWYWNQCCLDDNYYYNYCKCZHXXCCLGZQJGKWPPCQQJYSBZZXYJSQPXJPZBSBDSFNSFPZXHDWZTDWPPTFLZZBZDMYYPQJRSDZSQZSQXBDGCPZSWDWCSQZGMDHZXMWWFYBPDGPHTMJTHZSMMBGZMBZJCFZWFZBBZMQCFMBDMCJXLGPNJBBXGYHYYJGPTZGZMQBQTCGYXJXLWZKYDPDYMGCFTPFXYZTZXDZXTGKMTYBBCLBJASKYTSSQYYMSZXFJEWLXLLSZBQJJJAKLYLXLYCCTSXMCWFKKKBSXLLLLJYXTYLTJYYTDPJHNHNNKBYQNFQYYZBYYESSESSGDYHFHWTCJBSDZZTFDMXHCNJZYMQWSRYJDZJQPDQBBSTJGGFBKJBXTGQHNGWJXJGDLLTHZHHYYYYYYSXWTYYYCCBDBPYPZYCCZYJPZYWCBDLFWZCWJDXXHYHLHWZZXJTCZLCDPXUJCZZZLYXJJTXPHFXWPYWXZPTDZZBDZCYHJHMLXBQXSBYLRDTGJRRCTTTHYTCZWMXFYTWWZCWJWXJYWCSKYBZSCCTZQNHXNWXXKHKFHTSWOCCJYBCMPZZYKBNNZPBZHHZDLSYDDYTYFJPXYNGFXBYQXCBHXCPSXTYZDMKYSNXSXLHKMZXLYHDHKWHXXSSKQYHHCJYXGLHZXCSNHEKDTGZXQYPKDHEXTYKCNYMYYYPKQYYYKXZLTHJQTBYQHXBMYHSQCKWWYLLHCYYLNNEQXQWMCFBDCCMLJGGXDQKTLXKGNQCDGZJWYJJLYHHQTTTNWCHMXCXWHWSZJYDJCCDBQCDGDNYXZTHCQRXCBHZTQCBXWGQWYYBXHMBYMYQTYEXMQKYAQYRGYZSLFYKKQHYSSQYSHJGJCNXKZYCXSBXYXHYYLSTYCXQTHYSMGSCPMMGCCCCCMTZTASMGQZJHKLOSQYLSWTMXSYQKDZLJQQYPLSYCZTCQQPBBQJZCLPKHQZYYXXDTDDTSJCXFFLLCHQXMJLWCJCXTSPYCXNDTJSHJWXDQQJSKXYAMYLSJHMLALYKXCYYDMNMDQMXMCZNNCYBZKKYFLMCHCMLHXRCJJHSYLNMTJZGZGYWJXSRXCWJGJQHQZDQJDCJJZKJKGDZQGJJYJYLXZXXCDQHHHEYTMHLFSBDJSYYSHFYSTCZQLPBDRFRZTZYKYWHSZYQKWDQZRKMSYNBCRXQBJYFAZPZZEDZCJYWBCJWHYJBQSZYWRYSZPTDKZPFPBNZTKLQYHBBZPNPPTYZZYBQNYDCPJMMCYCQMCYFZZDCMNLFPBPLNGQJTBTTNJZPZBBZNJKLJQYLNBZQHKSJZNGGQSZZKYXSHPZSNBCGZKDDZQANZHJKDRTLZLSWJLJZLYWTJNDJZJHXYAYNCBGTZCSSQMNJPJYTYSWXZFKWJQTKHTZPLBHSNJZSYZBWZZZZLSYLSBJHDWWQPSLMMFBJDWAQYZTCJTBNNWZXQXCDSLQGDSDPDZHJTQQPSWLYYJZLGYXYZLCTCBJTKTYCZJTQKBSJLGMGZDMCSGPYNJZYQYYKNXRPWSZXMTNCSZZYXYBYHYZAXYWQCJTLLCKJJTJHGDXDXYQYZZBYWDLWQCGLZGJGQRQZCZSSBCRPCSKYDZNXJSQGXSSJMYDNSTZTPBDLTKZWXQWQTZEXNQCZGWEZKSSBYBRTSSSLCCGBPSZQSZLCCGLLLZXHZQTHCZMQGYZQZNMCOCSZJMMZSQPJYGQLJYJPPLDXRGZYXCCSXHSHGTZNLZWZKJCXTCFCJXLBMQBCZZWPQDNHXLJCTHYZLGYLNLSZZPCXDSCQQHJQKSXZPBAJYEMSMJTZDXLCJYRYYNWJBNGZZTMJXLTBSLYRZPYLSSCNXPHLLHYLLQQZQLXYMRSYCXZLMMCZLTZSDWTJJLLNZGGQXPFSKYGYGHBFZPDKMWGHCXMSGDXJMCJZDYCABXJDLNBCDQYGSKYDQTXDJJYXMSZQAZDZFSLQXYJSJZYLBTXXWXQQZBJZUFBBLYLWDSLJHXJYZJWTDJCZFQZQZZDZSXZZQLZCDZFJHYSPYMPQZMLPPLFFXJJNZZYLSJEYQZFPFZKSYWJJJHRDJZZXTXXGLGHYDXCSKYSWMMZCWYBAZBJKSHFHJCXMHFQHYXXYZFTSJYZFXYXPZLCHMZMBXHZZSXYFYMNCWDABAZLXKTCSHHXKXJJZJSTHYGXSXYYHHHJWXKZXSSBZZWHHHCWTZZZPJXSNXQQJGZYZYWLLCWXZFXXYXYHXMKYYSWSQMNLNAYCYSPMJKHWCQHYLAJJMZXHMMCNZHBHXCLXTJPLTXYJHDYYLTTXFSZHYXXSJBJYAYRSMXYPLCKDUYHLXRLNLLSTYZYYQYGYHHSCCSMZCTZQXKYQFPYYRPFFLKQUNTSZLLZMWWTCQQYZWTLLMLMPWMBZSSTZRBPDDTLQJJBXZCSRZQQYGWCSXFWZLXCCRSZDZMCYGGDZQSGTJSWLJMYMMZYHFBJDGYXCCPSHXNZCSBSJYJGJMPPWAFFYFNXHYZXZYLREMZGZCYZSSZDLLJCSQFNXZKPTXZGXJJGFMYYYSNBTYLBNLHPFZDCYFBMGQRRSSSZXYSGTZRNYDZZCDGPJAFJFZKNZBLCZSZPSGCYCJSZLMLRSZBZZLDLSLLYSXSQZQLYXZLSKKBRXBRBZCYCXZZZEEYFGKLZLYYHGZSGZLFJHGTGWKRAAJYZKZQTSSHJJXDCYZUYJLZYRZDQQHGJZXSSZBYKJPBFRTJXLLFQWJHYLQTYMBLPZDXTZYGBDHZZRBGXHWNJTJXLKSCFSMWLSDQYSJTXKZSCFWJLBXFTZLLJZLLQBLSQMQQCGCZFPBPHZCZJLPYYGGDTGWDCFCZQYYYQYSSCLXZSKLZZZGFFCQNWGLHQYZJJCZLQZZYJPJZZBPDCCMHJGXDQDGDLZQMFGPSYTSDYFWWDJZJYSXYYCZCYHZWPBYKXRYLYBHKJKSFXTZJMMCKHLLTNYYMSYXYZPYJQYCSYCWMTJJKQYRHLLQXPSGTLYYCLJSCPXJYZFNMLRGJJTYZBXYZMSJYJHHFZQMSYXRSZCWTLRTQZSSTKXGQKGSPTGCZNJSJCQCXHMXGGZTQYDJKZDLBZSXJLHYQGGGTHQSZPYHJHHGYYGKGGCWJZZYLCZLXQSFTGZSLLLMLJSKCTBLLZZSZMMNYTPZSXQHJCJYQXYZXZQZCPSHKZZYSXCDFGMWQRLLQXRFZTLYSTCTMJCXJJXHJNXTNRZTZFQYHQGLLGCXSZSJDJLJCYDSJTLNYXHSZXCGJZYQPYLFHDJSBPCCZHJJJQZJQDYBSSLLCMYTTMQTBHJQNNYGKYRQYQMZGCJKPDCGMYZHQLLSLLCLMHOLZGDYYFZSLJCQZLYLZQJESHNYLLJXGJXLYSYYYXNBZLJSSZCQQCJYLLZLTJYLLZLLBNYLGQCHXYYXOXCXQKYJXXXYKLXSXXYQXCYKQXQCSGYXXYQXYGYTQOHXHXPYXXXULCYEYCHZZCBWQBBWJQZSCSZSSLZYLKDESJZWMYMCYTSDSXXSCJPQQSQYLYYZYCMDJDZYWCBTJSYDJKCYDDJLBDJJSODZYSYXQQYXDHHGQQYQHDYXWGMMMAJDYBBBPPBCMUUPLJZSMTXERXJMHQNUTPJDCBSSMSSSTKJTSSMMTRCPLZSZMLQDSDMJMQPNQDXCFYNBFSDQXYXHYAYKQYDDLQYYYSSZBYDSLNTFQTZQPZMCHDHCZCWFDXTMYQSPHQYYXSRGJCWTJTZZQMGWJJTJHTQJBBHWZPXXHYQFXXQYWYYHYSCDYDHHQMNMTMWCPBSZPPZZGLMZFOLLCFWHMMSJZTTDHZZYFFYTZZGZYSKYJXQYJZQBHMBZZLYGHGFMSHPZFZSNCLPBQSNJXZSLXXFPMTYJYGBXLLDLXPZJYZJYHHZCYWHJYLSJEXFSZZYWXKZJLUYDTMLYMQJPWXYHXSKTQJEZRPXXZHHMHWQPWQLYJJQJJZSZCPHJLCHHNXJLQWZJHBMZYXBDHHYPZLHLHLGFWLCHYYTLHJXCJMSCPXSTKPNHQXSRTYXXTESYJCTLSSLSTDLLLWWYHDHRJZSFGXTSYCZYNYHTDHWJSLHTZDQDJZXXQHGYLTZPHCSQFCLNJTCLZPFSTPDYNYLGMJLLYCQHYSSHCHYLHQYQTMZYPBYWRFQYKQSYSLZDQJMPXYYSSRHZJNYWTQDFZBWWTWWRXCWHGYHXMKMYYYQMSMZHNGCEPMLQQMTCWCTMMPXJPJJHFXYYZSXZHTYBMSTSYJTTQQQYYLHYNPYQZLCYZHZWSMYLKFJXLWGXYPJYTYSYXYMZCKTTWLKSMZSYLMPWLZWXWQZSSAQSYXYRHSSNTSRAPXCPWCMGDXHXZDZYFJHGZTTSBJHGYZSZYSMYCLLLXBTYXHBBZJKSSDMALXHYCFYGMQYPJYCQXJLLLJGSLZGQLYCJCCZOTYXMTMTTLLWTGPXYMZMKLPSZZZXHKQYSXCTYJZYHXSHYXZKXLZWPSQPYHJWPJPWXQQYLXSDHMRSLZZYZWTTCYXYSZZSHBSCCSTPLWSSCJCHNLCGCHSSPHYLHFHHXJSXYLLNYLSZDHZXYLSXLWZYKCLDYAXZCMDDYSPJTQJZLNWQPSSSWCTSTSZLBLNXSMNYYMJQBQHRZWTYYDCHQLXKPZWBGQYBKFCMZWPZLLYYLSZYDWHXPSBCMLJBSCGBHXLQHYRLJXYSWXWXZSLDFHLSLYNJLZYFLYJYCDRJLFSYZFSLLCQYQFGJYHYXZLYLMSTDJCYHBZLLNWLXXYGYYHSMGDHXXHHLZZJZXCZZZCYQZFNGWPYLCPKPYYPMCLQKDGXZGGWQBDXZZKZFBXXLZXJTPJPTTBYTSZZDWSLCHZHSLTYXHQLHYXXXYYZYSWTXZKHLXZXZPYHGCHKCFSYHUTJRLXFJXPTZTWHPLYXFCRHXSHXKYXXYHZQDXQWULHYHMJTBFLKHTXCWHJFWJCFPQRYQXCYYYQYGRPYWSGSUNGWCHKZDXYFLXXHJJBYZWTSXXNCYJJYMSWZJQRMHXZWFQSYLZJZGBHYNSLBGTTCSYBYXXWXYHXYYXNSQYXMQYWRGYQLXBBZLJSYLPSYTJZYHYZAWLRORJMKSCZJXXXYXCHDYXRYXXJDTSQFXLYLTSFFYXLMTYJMJUYYYXLTZCSXQZQHZXLYYXZHDNBRXXXJCTYHLBRLMBRLLAXKYLLLJLYXXLYCRYLCJTGJCMTLZLLCYZZPZPCYAWHJJFYBDYYZSMPCKZDQYQPBPCJPDCYZMDPBCYYDYCNNPLMTMLRMFMMGWYZBSJGYGSMZQQQZTXMKQWGXLLPJGZBQCDJJJFPKJKCXBLJMSWMDTQJXLDLPPBXCWRCQFBFQJCZAHZGMYKPHYYHZYKNDKZMBPJYXPXYHLFPNYYGXJDBKXNXHJMZJXSTRSTLDXSKZYSYBZXJLXYSLBZYSLHXJPFXPQNBYLLJQKYGZMCYZZYMCCSLCLHZFWFWYXZMWSXTYNXJHPYYMCYSPMHYSMYDYSHQYZCHMJJMZCAAGCFJBBHPLYZYLXXSDJGXDHKXXTXXNBHRMLYJSLTXMRHNLXQJXYZLLYSWQGDLBJHDCGJYQYCMHWFMJYBMBYJYJWYMDPWHXQLDYGPDFXXBCGJSPCKRSSYZJMSLBZZJFLJJJLGXZGYXYXLSZQYXBEXYXHGCXBPLDYHWETTWWCJMBTXCHXYQXLLXFLYXLLJLSSFWDPZSMYJCLMWYTCZPCHQEKCQBWLCQYDPLQPPQZQFJQDJHYMMCXTXDRMJWRHXCJZYLQXDYYNHYYHRSLSRSYWWZJYMTLTLLGTQCJZYABTCKZCJYCCQLJZQXALMZYHYWLWDXZXQDLLQSHGPJFJLJHJABCQZDJGTKHSSTCYJLPSWZLXZXRWGLDLZRLZXTGSLLLLZLYXXWGDZYGBDPHZPBRLWSXQBPFDWOFMWHLYPCBJCCLDMBZPBZZLCYQXLDOMZBLZWPDWYYGDSTTHCSQSCCRSSSYSLFYBFNTYJSZDFNDPDHDZZMBBLSLCMYFFGTJJQWFTMTPJWFNLBZCMMJTGBDZLQLPYFHYYMJYLSDCHDZJWJCCTLJCLDTLJJCPDDSQDSSZYBNDBJLGGJZXSXNLYCYBJXQYCBYLZCFZPPGKCXZDZFZTJJFJSJXZBNZYJQTTYJYHTYCZHYMDJXTTMPXSPLZCDWSLSHXYPZGTFMLCJTYCBPMGDKWYCYZCDSZZYHFLYCTYGWHKJYYLSJCXGYWJCBLLCSNDDBTZBSCLYZCZZSSQDLLMQYYHFSLQLLXFTYHABXGWNYWYYPLLSDLDLLBJCYXJZMLHLJDXYYQYTDLLLBUGBFDFBBQJZZMDPJHGCLGMJJPGAEHHBWCQXAXHHHZCHXYPHJAXHLPHJPGPZJQCQZGJJZZUZDMQYYBZZPHYHYBWHAZYJHYKFGDPFQSDLZMLJXKXGALXZDAGLMDGXMWZQYXXDXXPFDMMSSYMPFMDMMKXKSYZYSHDZKXSYSMMZZZMSYDNZZCZXFPLSTMZDNMXCKJMZTYYMZMZZMSXHHDCZJEMXXKLJSTLWLSQLYJZLLZJSSDPPMHNLZJCZYHMXXHGZCJMDHXTKGRMXFWMCGMWKDTKSXQMMMFZZYDKMSCLCMPCGMHSPXQPZDSSLCXKYXTWLWJYAHZJGZQMCSNXYYMMPMLKJXMHLMLQMXCTKZMJQYSZJSYSZHSYJZJCDAJZYBSDQJZGWZQQXFKDMSDJLFWEHKZQKJPEYPZYSZCDWYJFFMZZYLTTDZZEFMZLBNPPLPLPEPSZALLTYLKCKQZKGENQLWAGYXYDPXLHSXQQWQCQXQCLHYXXMLYCCWLYMQYSKGCHLCJNSZKPYZKCQZQLJPDMDZHLASXLBYDWQLWDNBQCRYDDZTJYBKBWSZDXDTNPJDTCTQDFXQQMGNXECLTTBKPWSLCTYQLPWYZZKLPYGZCQQPLLKCCYLPQMZCZQCLJSLQZDJXLDDHPZQDLJJXZQDXYZQKZLJCYQDYJPPYPQYKJYRMPCBYMCXKLLZLLFQPYLLLMBSGLCYSSLRSYSQTMXYXZQZFDZUYSYZTFFMZZSMZQHZSSCCMLYXWTPZGXZJGZGSJSGKDDHTQGGZLLBJDZLCBCHYXYZHZFYWXYZYMSDBZZYJGTSMTFXQYXQSTDGSLNXDLRYZZLRYYLXQHTXSRTZNGZXBNQQZFMYKMZJBZYMKBPNLYZPBLMCNQYZZZSJZHJCTZKHYZZJRDYZHNPXGLFZTLKGJTCTSSYLLGZRZBBQZZKLPKLCZYSSUYXBJFPNJZZXCDWXZYJXZZDJJKGGRSRJKMSMZJLSJYWQSKYHQJSXPJZZZLSNSHRNYPZTWCHKLPSRZLZXYJQXQKYSJYCZTLQZYBBYBWZPQDWWYZCYTJCJXCKCWDKKZXSGKDZXWWYYJQYYTCYTDLLXWKCZKKLCCLZCQQDZLQLCSFQCHQHSFSMQZZLNBJJZBSJHTSZDYSJQJPDLZCDCWJKJZZLPYCGMZWDJJBSJQZSYZYHHXJPBJYDSSXDZNCGLQMBTSFSBPDZDLZNFGFJGFSMPXJQLMBLGQCYYXBQKDJJQYRFKZTJDHCZKLBSDZCFJTPLLJGXHYXZCSSZZXSTJYGKGCKGYOQXJPLZPBPGTGYJZGHZQZZLBJLSQFZGKQQJZGYCZBZQTLDXRJXBSXXPZXHYZYCLWDXJJHXMFDZPFZHQHQMQGKSLYHTYCGFRZGNQXCLPDLBZCSCZQLLJBLHBZCYPZZPPDYMZZSGYHCKCPZJGSLJLNSCDSLDLXBMSTLDDFJMKDJDHZLZXLSZQPQPGJLLYBDSZGQLBZLSLKYYHZTTNTJYQTZZPSZQZTLLJTYYLLQLLQYZQLBDZLSLYYZYMDFSZSNHLXZNCZQZPBWSKRFBSYZMTHBLGJPMCZZLSTLXSHTCSYZLZBLFEQHLXFLCJLYLJQCBZLZJHHSSTBRMHXZHJZCLXFNBGXGTQJCZTMSFZKJMSSNXLJKBHSJXNTNLZDNTLMSJXGZJYJCZXYJYJWRWWQNZTNFJSZPZSHZJFYRDJSFSZJZBJFZQZZHZLXFYSBZQLZSGYFTZDCSZXZJBQMSZKJRHYJZCKMJKHCHGTXKXQGLXPXFXTRTYLXJXHDTSJXHJZJXZWZLCQSBTXWXGXTXXHXFTSDKFJHZYJFJXRZSDLLLTQSQQZQWZXSYQTWGWBZCGZLLYZBCLMQQTZHZXZXLJFRMYZFLXYSQXXJKXRMQDZDMMYYBSQBHGZMWFWXGMXLZPYYTGZYCCDXYZXYWGSYJYZNBHPZJSQSYXSXRTFYZGRHZTXSZZTHCBFCLSYXZLZQMZLMPLMXZJXSFLBYZMYQHXJSXRXSQZZZSSLYFRCZJRCRXHHZXQYDYHXSJJHZCXZBTYNSYSXJBQLPXZQPYMLXZKYXLXCJLCYSXXZZLXDLLLJJYHZXGYJWKJRWYHCPSGNRZLFZWFZZNSXGXFLZSXZZZBFCSYJDBRJKRDHHGXJLJJTGXJXXSTJTJXLYXQFCSGSWMSBCTLQZZWLZZKXJMLTMJYHSDDBXGZHDLBMYJFRZFSGCLYJBPMLYSMSXLSZJQQHJZFXGFQFQBPXZGYYQXGZTCQWYLTLGWSGWHRLFSFGZJMGMGBGTJFSYZZGZYZAFLSSPMLPFLCWBJZCLJJMZLPJJLYMQDMYYYFBGYGYZMLYZDXQYXRQQQHSYYYQXYLJTYXFSFSLLGNQCYHYCWFHCCCFXPYLYPLLZYXXXXXKQHHXSHJZCFZSCZJXCPZWHHHHHAPYLQALPQAFYHXDYLUKMZQGGGDDESRNNZLTZGCHYPPYSQJJHCLLJTOLNJPZLJLHYMHEYDYDSQYCDDHGZUNDZCLZYZLLZNTNYZGSLHSLPJJBDGWXPCDUTJCKLKCLWKLLCASSTKZZDNQNTTLYYZSSYSSZZRYLJQKCQDHHCRXRZYDGRGCWCGZQFFFPPJFZYNAKRGYWYQPQXXFKJTSZZXSWZDDFBBXTBGTZKZNPZZPZXZPJSZBMQHKCYXYLDKLJNYPKYGHGDZJXXEAHPNZKZTZCMXCXMMJXNKSZQNMNLWBWWXJKYHCPSTMCSQTZJYXTPCTPDTNNPGLLLZSJLSPBLPLQHDTNJNLYYRSZFFJFQWDPHZDWMRZCCLODAXNSSNYZRESTYJWJYJDBCFXNMWTTBYLWSTSZGYBLJPXGLBOCLHPCBJLTMXZLJYLZXCLTPNCLCKXTPZJSWCYXSFYSZDKNTLBYJCYJLLSTGQCBXRYZXBXKLYLHZLQZLNZCXWJZLJZJNCJHXMNZZGJZZXTZJXYCYYCXXJYYXJJXSSSJSTSSTTPPGQTCSXWZDCSYFPTFBFHFBBLZJCLZZDBXGCXLQPXKFZFLSYLTUWBMQJHSZBMDDBCYSCCLDXYCDDQLYJJWMQLLCSGLJJSYFPYYCCYLTJANTJJPWYCMMGQYYSXDXQMZHSZXPFTWWZQSWQRFKJLZJQQYFBRXJHHFWJJZYQAZMYFRHCYYBYQWLPEXCCZSTYRLTTDMQLYKMBBGMYYJPRKZNPBSXYXBHYZDJDNGHPMFSGMWFZMFQMMBCMZZCJJLCNUXYQLMLRYGQZCYXZLWJGCJCGGMCJNFYZZJHYCPRRCMTZQZXHFQGTJXCCJEAQCRJYHPLQLSZDJRBCQHQDYRHYLYXJSYMHZYDWLDFRYHBPYDTSSCNWBXGLPZMLZZTQSSCPJMXXYCSJYTYCGHYCJWYRXXLFEMWJNMKLLSWTXHYYYNCMMCWJDQDJZGLLJWJRKHPZGGFLCCSCZMCBLTBHBQJXQDSPDJZZGKGLFQYWBZYZJLTSTDHQHCTCBCHFLQMPWDSHYYTQWCNZZJTLBYMBPDYYYXSQKXWYYFLXXNCWCXYPMAELYKKJMZZZBRXYYQJFLJPFHHHYTZZXSGQQMHSPGDZQWBWPJHZJDYSCQWZKTXXSQLZYYMYSDZGRXCKKUJLWPYSYSCSYZLRMLQSYLJXBCXTLWDQZPCYCYKPPPNSXFYZJJRCEMHSZMSXLXGLRWGCSTLRSXBZGBZGZTCPLUJLSLYLYMTXMTZPALZXPXJTJWTCYYZLBLXBZLQMYLXPGHDSLSSDMXMBDZZSXWHAMLCZCPJMCNHJYSNSYGCHSKQMZZQDLLKABLWJXSFMOCDXJRRLYQZKJMYBYQLYHETFJZFRFKSRYXFJTWDSXXSYSQJYSLYXWJHSNLXYYXHBHAWHHJZXWMYLJCSSLKYDZTXBZSYFDXGXZJKHSXXYBSSXDPYNZWRPTQZCZENYGCXQFJYKJBZMLJCMQQXUOXSLYXXLYLLJDZBTYMHPFSTTQQWLHOKYBLZZALZXQLHZWRRQHLSTMYPYXJJXMQSJFNBXYXYJXXYQYLTHYLQYFMLKLJTMLLHSZWKZHLJMLHLJKLJSTLQXYLMBHHLNLZXQJHXCFXXLHYHJJGBYZZKBXSCQDJQDSUJZYYHZHHMGSXCSYMXFEBCQWWRBPYYJQTYZCYQYQQZYHMWFFHGZFRJFCDPXNTQYZPDYKHJLFRZXPPXZDBBGZQSTLGDGYLCQMLCHHMFYWLZYXKJLYPQHSYWMQQGQZMLZJNSQXJQSYJYCBEHSXFSZPXZWFLLBCYYJDYTDTHWZSFJMQQYJLMQXXLLDTTKHHYBFPWTYYSQQWNQWLGWDEBZWCMYGCULKJXTMXMYJSXHYBRWFYMWFRXYQMXYSZTZZTFYKMLDHQDXWYYNLCRYJBLPSXCXYWLSPRRJWXHQYPHTYDNXHHMMYWYTZCSQMTSSCCDALWZTCPQPYJLLQZYJSWXMZZMMYLMXCLMXCZMXMZSQTZPPQQBLPGXQZHFLJJHYTJSRXWZXSCCDLXTYJDCQJXSLQYCLZXLZZXMXQRJMHRHZJBHMFLJLMLCLQNLDXZLLLPYPSYJYSXCQQDCMQJZZXHNPNXZMEKMXHYKYQLXSXTXJYYHWDCWDZHQYYBGYBCYSCFGPSJNZDYZZJZXRZRQJJYMCANYRJTLDPPYZBSTJKXXZYPFDWFGZZRPYMTNGXZQBYXNBUFNQKRJQZMJEGRZGYCLKXZDSKKNSXKCLJSPJYYZLQQJYBZSSQLLLKJXTBKTYLCCDDBLSPPFYLGYDTZJYQGGKQTTFZXBDKTYYHYBBFYTYYBCLPDYTGDHRYRNJSPTCSNYJQHKLLLZSLYDXXWBCJQSPXBPJZJCJDZFFXXBRMLAZHCSNDLBJDSZBLPRZTSWSBXBCLLXXLZDJZSJPYLYXXYFTFFFBHJJXGBYXJPMMMPSSJZJMTLYZJXSWXTYLEDQPJMYGQZJGDJLQJWJQLLSJGJGYGMSCLJJXDTYGJQJQJCJZCJGDZZSXQGSJGGCXHQXSNQLZZBXHSGZXCXYLJXYXYYDFQQJHJFXDHCTXJYRXYSQTJXYEFYYSSYYJXNCYZXFXMSYSZXYYSCHSHXZZZGZZZGFJDLTYLNPZGYJYZYYQZPBXQBDZTZCZYXXYHHSQXSHDHGQHJHGYWSZTMZMLHYXGEBTYLZKQWYTJZRCLEKYSTDBCYKQQSAYXCJXWWGSBHJYZYDHCSJKQCXSWXFLTYNYZPZCCZJQTZWJQDZZZQZLJJXLSBHPYXXPSXSHHEZTXFPTLQYZZXHYTXNCFZYYHXGNXMYWXTZSJPTHHGYMXMXQZXTSBCZYJYXXTYYZYPCQLMMSZMJZZLLZXGXZAAJZYXJMZXWDXZSXZDZXLEYJJZQBHZWZZZQTZPSXZTDSXJJJZNYAZPHXYYSRNQDTHZHYYKYJHDZXZLSWCLYBZYECWCYCRYLCXNHZYDZYDYJDFRJJHTRSQTXYXJRJHOJYNXELXSFSFJZGHPZSXZSZDZCQZBYYKLSGSJHCZSHDGQGXYZGXCHXZJWYQWGYHKSSEQZZNDZFKWYSSTCLZSTSYMCDHJXXYWEYXCZAYDMPXMDSXYBSQMJMZJMTZQLPJYQZCGQHXJHHLXXHLHDLDJQCLDWBSXFZZYYSCHTYTYYBHECXHYKGJPXHHYZJFXHWHBDZFYZBCAPNPGNYDMSXHMMMMAMYNBYJTMPXYYMCTHJBZYFCGTYHWPHFTWZZEZSBZEGPFMTSKFTYCMHFLLHGPZJXZJGZJYXZSBBQSCZZLZCCSTPGXMJSFTCCZJZDJXCYBZLFCJSYZFGSZLYBCWZZBYZDZYPSWYJZXZBDSYUXLZZBZFYGCZXBZHZFTPBGZGEJBSTGKDMFHYZZJHZLLZZGJQZLSFDJSSCBZGPDLFZFZSZYZYZSYGCXSNXXCHCZXTZZLJFZGQSQYXZJQDCCZTQCDXZJYQJQCHXZTDLGSCXZSYQJQTZWLQDQZTQCHQQJZYEZZZPBWKDJFCJPZTYPQYQTTYNLMBDKTJZPQZQZZFPZSBNJLGYJDXJDZZKZGQKXDLPZJTCJDQBXDJQJSTCKNXBXZMSLYJCQMTJQWWCJQNJNLLLHJCWQTBZQYDZCZPZZDZYDDCYZZZCCJTTJFZDPRRTZTJDCQTQZDTJNPLZBCLLCTZSXKJZQZPZLBZRBTJDCXFCZDBCCJJLTQQPLDCGZDBBZJCQDCJWYNLLZYZCCDWLLXWZLXRXNTQQCZXKQLSGDFQTDDGLRLAJJTKUYMKQLLTZYTDYYCZGJWYXDXFRSKSTQTENQMRKQZHHQKDLDAZFKYPBGGPZREBZZYKZZSPEGJXGYKQZZZSLYSYYYZWFQZYLZZLZHWCHKYPQGNPGBLPLRRJYXCCSYYHSFZFYBZYYTGZXYLXCZWXXZJZBLFFLGSKHYJZEYJHLPLLLLCZGXDRZELRHGKLZZYHZLYQSZZJZQLJZFLNBHGWLCZCFJYSPYXZLZLXGCCPZBLLCYBBBBUBBCBPCRNNZCZYRBFSRLDCGQYYQXYGMQZWTZYTYJXYFWTEHZZJYWLCCNTZYJJZDEDPZDZTSYQJHDYMBJNYJZLXTSSTPHNDJXXBYXQTZQDDTJTDYYTGWSCSZQFLSHLGLBCZPHDLYZJYCKWTYTYLBNYTSDSYCCTYSZYYEBHEXHQDTWNYGYCLXTSZYSTQMYGZAZCCSZZDSLZCLZRQXYYELJSBYMXSXZTEMBBLLYYLLYTDQYSHYMRQWKFKBFXNXSBYCHXBWJYHTQBPBSBWDZYLKGZSKYHXQZJXHXJXGNLJKZLYYCDXLFYFGHLJGJYBXQLYBXQPQGZTZPLNCYPXDJYQYDYMRBESJYYHKXXSTMXRCZZYWXYQYBMCLLYZHQYZWQXDBXBZWZMSLPDMYSKFMZKLZCYQYCZLQXFZZYDQZPZYGYJYZMZXDZFYFYTTQTZHGSPCZMLCCYTZXJCYTJMKSLPZHYSNZLLYTPZCTZZCKTXDHXXTQCYFKSMQCCYYAZHTJPCYLZLYJBJXTPNYLJYYNRXSYLMMNXJSMYBCSYSYLZYLXJJQYLDZLPQBFZZBLFNDXQKCZFYWHGQMRDSXYCYTXNQQJZYYPFZXDYZFPRXEJDGYQBXRCNFYYQPGHYJDYZXGRHTKYLNWDZNTSMPKLBTHBPYSZBZTJZSZZJTYYXZPHSSZZBZCZPTQFZMYFLYPYBBJQXZMXXDJMTSYSKKBJZXHJCKLPSMKYJZCXTMLJYXRZZQSLXXQPYZXMKYXXXJCLJPRMYYGADYSKQLSNDHYZKQXZYZTCGHZTLMLWZYBWSYCTBHJHJFCWZTXWYTKZLXQSHLYJZJXTMPLPYCGLTBZZTLZJCYJGDTCLKLPLLQPJMZPAPXYZLKKTKDZCZZBNZDYDYQZJYJGMCTXLTGXSZLMLHBGLKFWNWZHDXUHLFMKYSLGXDTWWFRJEJZTZHYDXYKSHWFZCQSHKTMQQHTZHYMJDJSKHXZJZBZZXYMPAGQMSTPXLSKLZYNWRTSQLSZBPSPSGZWYHTLKSSSWHZZLYYTNXJGMJSZSUFWNLSOZTXGXLSAMMLBWLDSZYLAKQCQCTMYCFJBSLXCLZZCLXXKSBZQCLHJPSQPLSXXCKSLNHPSFQQYTXYJZLQLDXZQJZDYYDJNZPTUZDSKJFSLJHYLZSQZLBTXYDGTQFDBYAZXDZHZJNHHQBYKNXJJQCZMLLJZKSPLDYCLBBLXKLELXJLBQYCXJXGCNLCQPLZLZYJTZLJGYZDZPLTQCSXFDMNYCXGBTJDCZNBGBQYQJWGKFHTNPYQZQGBKPBBYZMTJDYTBLSQMPSXTBNPDXKLEMYYCJYNZCTLDYKZZXDDXHQSHDGMZSJYCCTAYRZLPYLTLKXSLZCGGEXCLFXLKJRTLQJAQZNCMBYDKKCXGLCZJZXJHPTDJJMZQYKQSECQZDSHHADMLZFMMZBGNTJNNLGBYJBRBTMLBYJDZXLCJLPLDLPCQDHLXZLYCBLCXZZJADJLNZMMSSSMYBHBSQKBHRSXXJMXSDZNZPXLGBRHWGGFCXGMSKLLTSJYYCQLTSKYWYYHYWXBXQYWPYWYKQLSQPTNTKHQCWDQKTWPXXHCPTHTWUMSSYHBWCRWXHJMKMZNGWTMLKFGHKJYLSYYCXWHYECLQHKQHTTQKHFZLDXQWYZYYDESBPKYRZPJFYYZJCEQDZZDLATZBBFJLLCXDLMJSSXEGYGSJQXCWBXSSZPDYZCXDNYXPPZYDLYJCZPLTXLSXYZYRXCYYYDYLWWNZSAHJSYQYHGYWWAXTJZDAXYSRLTDPSSYYFNEJDXYZHLXLLLZQZSJNYQYQQXYJGHZGZCYJCHZLYCDSHWSHJZYJXCLLNXZJJYYXNFXMWFPYLCYLLABWDDHWDXJMCXZTZPMLQZHSFHZYNZTLLDYWLSLXHYMMYLMBWWKYXYADTXYLLDJPYBPWUXJMWMLLSAFDLLYFLBHHHBQQLTZJCQJLDJTFFKMMMBYTHYGDCQRDDWRQJXNBYSNWZDBYYTBJHPYBYTTJXAAHGQDQTMYSTQXKBTZPKJLZRBEQQSSMJJBDJOTGTBXPGBKTLHQXJJJCTHXQDWJLWRFWQGWSHCKRYSWGFTGYGBXSDWDWRFHWYTJJXXXJYZYSLPYYYPAYXHYDQKXSHXYXGSKQHYWFDDDPPLCJLQQEEWXKSYYKDYPLTJTHKJLTCYYHHJTTPLTZZCDLTHQKZXQYSTEEYWYYZYXXYYSTTJKLLPZMCYHQGXYHSRMBXPLLNQYDQHXSXXWGDQBSHYLLPJJJTHYJKYPPTHYYKTYEZYENMDSHLCRPQFDGFXZPSFTLJXXJBSWYYSKSFLXLPPLBBBLBSFXFYZBSJSSYLPBBFFFFSSCJDSTZSXZRYYSYFFSYZYZBJTBCTSBSDHRTJJBYTCXYJEYLXCBNEBJDSYXYKGSJZBXBYTFZWGENYHHTHZHHXFWGCSTBGXKLSXYWMTMBYXJSTZSCDYQRCYTWXZFHMYMCXLZNSDJTTTXRYCFYJSBSDYERXJLJXBBDEYNJGHXGCKGSCYMBLXJMSZNSKGXFBNBPTHFJAAFXYXFPXMYPQDTZCXZZPXRSYWZDLYBBKTYQPQJPZYPZJZNJPZJLZZFYSBTTSLMPTZRTDXQSJEHBZYLZDHLJSQMLHTXTJECXSLZZSPKTLZKQQYFSYGYWPCPQFHQHYTQXZKRSGTTSQCZLPTXCDYYZXSQZSLXLZMYCPCQBZYXHBSXLZDLTCDXTYLZJYYZPZYZLTXJSJXHLPMYTXCQRBLZSSFJZZTNJYTXMYJHLHPPLCYXQJQQKZZSCPZKSWALQSBLCCZJSXGWWWYGYKTJBBZTDKHXHKGTGPBKQYSLPXPJCKBMLLXDZSTBKLGGQKQLSBKKTFXRMDKBFTPZFRTBBRFERQGXYJPZSSTLBZTPSZQZSJDHLJQLZBPMSMMSXLQQNHKNBLRDDNXXDHDDJCYYGYLXGZLXSYGMQQGKHBPMXYXLYTQWLWGCPBMQXCYZYDRJBHTDJYHQSHTMJSBYPLWHLZFFNYPMHXXHPLTBQPFBJWQDBYGPNZTPFZJGSDDTQSHZEAWZZYLLTYYBWJKXXGHLFKXDJTMSZSQYNZGGSWQSPHTLSSKMCLZXYSZQZXNCJDQGZDLFNYKLJCJLLZLMZZNHYDSSHTHZZLZZBBHQZWWYCRZHLYQQJBEYFXXXWHSRXWQHWPSLMSSKZTTYGYQQWRSLALHMJTQJSMXQBJJZJXZYZKXBYQXBJXSHZTSFJLXMXZXFGHKZSZGGYLCLSARJYHSLLLMZXELGLXYDJYTLFBHBPNLYZFBBHPTGJKWETZHKJJXZXXGLLJLSTGSHJJYQLQZFKCGNNDJSSZFDBCTWWSEQFHQJBSAQTGYPQLBXBMMYWXGSLZHGLZGQYFLZBYFZJFRYSFMBYZHQGFWZSYFYJJPHZBYYZFFWODGRLMFTWLBZGYCQXCDJYGZYYYYTYTYDWEGAZYHXJLZYYHLRMGRXXZCLHNELJJTJTPWJYBJJBXJJTJTEEKHWSLJPLPSFYZPQQBDLQJJTYYQLYZKDKSQJYYQZLDQTGJQYZJSUCMRYQTHTEJMFCTYHYPKMHYZWJDQFHYYXWSHCTXRLJHQXHCCYYYJLTKTTYTMXGTCJTZAYYOCZLYLBSZYWJYTSJYHBYSHFJLYGJXXTMZYYLTXXYPZLXYJZYZYYPNHMYMDYYLBLHLSYYQQLLNJJYMSOYQBZGDLYXYLCQYXTSZEGXHZGLHWBLJHEYXTWQMAKBPQCGYSHHEGQCMWYYWLJYJHYYZLLJJYLHZYHMGSLJLJXCJJYCLYCJPCPZJZJMMYLCQLNQLJQJSXYJMLSZLJQLYCMMHCFMMFPQQMFYLQMCFFQMMMMHMZNFHHJGTTHHKHSLNCHHYQDXTMMQDCYZYXYQMYQYLTDCYYYZAZZCYMZYDLZFFFMMYCQZWZZMABTBYZTDMNZZGGDFTYPCGQYTTSSFFWFDTZQSSYSTWXJHXYTSXXYLBYQHWWKXHZXWZNNZZJZJJQJCCCHYYXBZXZCYZTLLCQXYNJYCYYCYNZZQYYYEWYCZDCJYCCHYJLBTZYYCQWMPWPYMLGKDLDLGKQQBGYCHJXY";
+
+ // 此处收录了375个多音字
+ string multiPinyin = "19969:DZ,19975:WM,19988:QJ,20048:YL,20056:SC,20060:NM,20094:QG,20127:QJ,20167:QC,20193:YG,20250:KH,20256:ZC,20282:SC,20285:QJG,20291:TD,20314:YD,20340:NE,20375:TD,20389:YJ,20391:CZ,20415:PB,20446:YS,20447:SQ,20504:TC,20608:KG,20854:QJ,20857:ZC,20911:PF,20504:TC,20608:KG,20854:QJ,20857:ZC,20911:PF,20985:AW,21032:PB,21048:XQ,21049:SC,21089:YS,21119:JC,21242:SB,21273:SC,21305:YP,21306:QO,21330:ZC,21333:SDC,21345:QK,21378:CA,21397:SC,21414:XS,21442:SC,21477:JG,21480:TD,21484:ZS,21494:YX,21505:YX,21512:HG,21523:XH,21537:PB,21542:PF,21549:KH,21571:E,21574:DA,21588:TD,21589:O,21618:ZC,21621:KHA,21632:ZJ,21654:KG,21679:LKG,21683:KH,21710:A,21719:YH,21734:WOE,21769:A,21780:WN,21804:XH,21834:A,21899:ZD,21903:RN,21908:WO,21939:ZC,21956:SA,21964:YA,21970:TD,22003:A,22031:JG,22040:XS,22060:ZC,22066:ZC,22079:MH,22129:XJ,22179:XA,22237:NJ,22244:TD,22280:JQ,22300:YH,22313:XW,22331:YQ,22343:YJ,22351:PH,22395:DC,22412:TD,22484:PB,22500:PB,22534:ZD,22549:DH,22561:PB,22612:TD,22771:KQ,22831:HB,22841:JG,22855:QJ,22865:XQ,23013:ML,23081:WM,23487:SX,23558:QJ,23561:YW,23586:YW,23614:YW,23615:SN,23631:PB,23646:ZS,23663:ZT,23673:YG,23762:TD,23769:ZS,23780:QJ,23884:QK,24055:XH,24113:DC,24162:ZC,24191:GA,24273:QJ,24324:NL,24377:TD,24378:QJ,24439:PF,24554:ZS,24683:TD,24694:WE,24733:LK,24925:TN,25094:ZG,25100:XQ,25103:XH,25153:PB,25170:PB,25179:KG,25203:PB,25240:ZS,25282:FB,25303:NA,25324:KG,25341:ZY,25373:WZ,25375:XJ,25384:A,25457:A,25528:SD,25530:SC,25552:TD,25774:ZC,25874:ZC,26044:YW,26080:WM,26292:PB,26333:PB,26355:ZY,26366:CZ,26397:ZC,26399:QJ,26415:ZS,26451:SB,26526:ZC,26552:JG,26561:TD,26588:JG,26597:CZ,26629:ZS,26638:YL,26646:XQ,26653:KG,26657:XJ,26727:HG,26894:ZC,26937:ZS,26946:ZC,26999:KJ,27099:KJ,27449:YQ,27481:XS,27542:ZS,27663:ZS,27748:TS,27784:SC,27788:ZD,27795:TD,27812:O,27850:PB,27852:MB,27895:SL,27898:PL,27973:QJ,27981:KH,27986:HX,27994:XJ,28044:YC,28065:WG,28177:SM,28267:QJ,28291:KH,28337:ZQ,28463:TL,28548:DC,28601:TD,28689:PB,28805:JG,28820:QG,28846:PB,28952:TD,28975:ZC,29100:A,29325:QJ,29575:SL,29602:FB,30010:TD,30044:CX,30058:PF,30091:YSP,30111:YN,30229:XJ,30427:SC,30465:SX,30631:YQ,30655:QJ,30684:QJG,30707:SD,30729:XH,30796:LG,30917:PB,31074:NM,31085:JZ,31109:SC,31181:ZC,31192:MLB,31293:JQ,31400:YX,31584:YJ,31896:ZN,31909:ZY,31995:XJ,32321:PF,32327:ZY,32418:HG,32420:XQ,32421:HG,32438:LG,32473:GJ,32488:TD,32521:QJ,32527:PB,32562:ZSQ,32564:JZ,32735:ZD,32793:PB,33071:PF,33098:XL,33100:YA,33152:PB,33261:CX,33324:BP,33333:TD,33406:YA,33426:WM,33432:PB,33445:JG,33486:ZN,33493:TS,33507:QJ,33540:QJ,33544:ZC,33564:XQ,33617:YT,33632:QJ,33636:XH,33637:YX,33694:WG,33705:PF,33728:YW,33882:SR,34067:WM,34074:YW,34121:QJ,34255:ZC,34259:XL,34425:JH,34430:XH,34485:KH,34503:YS,34532:HG,34552:XS,34558:YE,34593:ZL,34660:YQ,34892:XH,34928:SC,34999:QJ,35048:PB,35059:SC,35098:ZC,35203:TQ,35265:JX,35299:JX,35782:SZ,35828:YS,35830:E,35843:TD,35895:YG,35977:MH,36158:JG,36228:QJ,36426:XQ,36466:DC,36710:JC,36711:ZYG,36767:PB,36866:SK,36951:YW,37034:YX,37063:XH,37218:ZC,37325:ZC,38063:PB,38079:TD,38085:QY,38107:DC,38116:TD,38123:YD,38224:HG,38241:XTC,38271:ZC,38415:YE,38426:KH,38461:YD,38463:AE,38466:PB,38477:XJ,38518:YT,38551:WK,38585:ZC,38704:XS,38739:LJ,38761:GJ,38808:SQ,39048:JG,39049:XJ,39052:HG,39076:CZ,39271:XT,39534:TD,39552:TD,39584:PB,39647:SB,39730:LG,39748:TPB,40109:ZQ,40479:ND,40516:HG,40536:HG,40583:QJ,40765:YQ,40784:QJ,40840:YK,40863:QJG,";
+ string resStr = string.Empty;
+ int i, j, uni;
+ uni = HanZi;
+ if (uni > 40869 || uni < 19968)
+ return resStr;
+
+ // 返回该字符在Unicode字符集中的编码值
+ i = multiPinyin.IndexOf(uni.ToString());
+
+ // 检查是否是多音字,是按多音字处理,不是就直接在strChineseFirstPY字符串中找对应的首字母
+ if (i < 0)
+ {
+ // 获取非多音字汉字首字母
+ resStr = strChineseFirstPY[uni - 19968].ToString();
}
else
{
- // 构造第一个汉字返回结果
- for (m = 0; m < tmpStr.Length - 1; m++)
- returnStr += tmpStr[m] + ",";
- returnStr += tmpStr[tmpStr.Length - 1];
+ // 获取多音字汉字首字母
+ j = multiPinyin.IndexOf(",", i);
+ resStr = multiPinyin.Substring(i + 6, j - i - 6);
}
- }
+
+ return resStr;
}
+ #endregion
- // 返回处理结果字符串,以,分隔每个拼音组合
- return returnStr;
- }
-
- private static string GetPinyin(char HanZi)
-
- // 获取单个汉字对应的拼音首字符字符串
- {
- // 汉字拼音首字母列表 本列表包含了20902个汉字,收录的字符的Unicode编码范围为19968至40869
-
- string strChineseFirstPY = "YDYQSXMWZSSXJBYMGCCZQPSSQBYCDSCDQLDYLYBSSJGYZZJJFKCCLZDHWDWZJLJPFYYNWJJTMYHZWZHFLZPPQHGSCYYYNJQYXXGJHHSDSJNKKTMOMLCRXYPSNQSECCQZGGLLYJLMYZZSECYKYYHQWJSSGGYXYZYJWWKDJHYCHMYXJTLXJYQBYXZLDWRDJRWYSRLDZJPCBZJJBRCFTLECZSTZFXXZHTRQHYBDLYCZSSYMMRFMYQZPWWJJYFCRWFDFZQPYDDWYXKYJAWJFFXYPSFTZYHHYZYSWCJYXSCLCXXWZZXNBGNNXBXLZSZSBSGPYSYZDHMDZBQBZCWDZZYYTZHBTSYYBZGNTNXQYWQSKBPHHLXGYBFMJEBJHHGQTJCYSXSTKZHLYCKGLYSMZXYALMELDCCXGZYRJXSDLTYZCQKCNNJWHJTZZCQLJSTSTBNXBTYXCEQXGKWJYFLZQLYHYXSPSFXLMPBYSXXXYDJCZYLLLSJXFHJXPJBTFFYABYXBHZZBJYZLWLCZGGBTSSMDTJZXPTHYQTGLJSCQFZKJZJQNLZWLSLHDZBWJNCJZYZSQQYCQYRZCJJWYBRTWPYFTWEXCSKDZCTBZHYZZYYJXZCFFZZMJYXXSDZZOTTBZLQWFCKSZSXFYRLNYJMBDTHJXSQQCCSBXYYTSYFBXDZTGBCNSLCYZZPSAZYZZSCJCSHZQYDXLBPJLLMQXTYDZXSQJTZPXLCGLQTZWJBHCTSYJSFXYEJJTLBGXSXJMYJQQPFZASYJNTYDJXKJCDJSZCBARTDCLYJQMWNQNCLLLKBYBZZSYHQQLTWLCCXTXLLZNTYLNEWYZYXCZXXGRKRMTCNDNJTSYYSSDQDGHSDBJGHRWRQLYBGLXHLGTGXBQJDZPYJSJYJCTMRNYMGRZJCZGJMZMGXMPRYXKJNYMSGMZJYMKMFXMLDTGFBHCJHKYLPFMDXLQJJSMTQGZSJLQDLDGJYCALCMZCSDJLLNXDJFFFFJCZFMZFFPFKHKGDPSXKTACJDHHZDDCRRCFQYJKQCCWJDXHWJLYLLZGCFCQDSMLZPBJJPLSBCJGGDCKKDEZSQCCKJGCGKDJTJDLZYCXKLQSCGJCLTFPCQCZGWPJDQYZJJBYJHSJDZWGFSJGZKQCCZLLPSPKJGQJHZZLJPLGJGJJTHJJYJZCZMLZLYQBGJWMLJKXZDZNJQSYZMLJLLJKYWXMKJLHSKJGBMCLYYMKXJQLBMLLKMDXXKWYXYSLMLPSJQQJQXYXFJTJDXMXXLLCXQBSYJBGWYMBGGBCYXPJYGPEPFGDJGBHBNSQJYZJKJKHXQFGQZKFHYGKHDKLLSDJQXPQYKYBNQSXQNSZSWHBSXWHXWBZZXDMNSJBSBKBBZKLYLXGWXDRWYQZMYWSJQLCJXXJXKJEQXSCYETLZHLYYYSDZPAQYZCMTLSHTZCFYZYXYLJSDCJQAGYSLCQLYYYSHMRQQKLDXZSCSSSYDYCJYSFSJBFRSSZQSBXXPXJYSDRCKGJLGDKZJZBDKTCSYQPYHSTCLDJDHMXMCGXYZHJDDTMHLTXZXYLYMOHYJCLTYFBQQXPFBDFHHTKSQHZYYWCNXXCRWHOWGYJLEGWDQCWGFJYCSNTMYTOLBYGWQWESJPWNMLRYDZSZTXYQPZGCWXHNGPYXSHMYQJXZTDPPBFYHZHTJYFDZWKGKZBLDNTSXHQEEGZZYLZMMZYJZGXZXKHKSTXNXXWYLYAPSTHXDWHZYMPXAGKYDXBHNHXKDPJNMYHYLPMGOCSLNZHKXXLPZZLBMLSFBHHGYGYYGGBHSCYAQTYWLXTZQCEZYDQDQMMHTKLLSZHLSJZWFYHQSWSCWLQAZYNYTLSXTHAZNKZZSZZLAXXZWWCTGQQTDDYZTCCHYQZFLXPSLZYGPZSZNGLNDQTBDLXGTCTAJDKYWNSYZLJHHZZCWNYYZYWMHYCHHYXHJKZWSXHZYXLYSKQYSPSLYZWMYPPKBYGLKZHTYXAXQSYSHXASMCHKDSCRSWJPWXSGZJLWWSCHSJHSQNHCSEGNDAQTBAALZZMSSTDQJCJKTSCJAXPLGGXHHGXXZCXPDMMHLDGTYBYSJMXHMRCPXXJZCKZXSHMLQXXTTHXWZFKHCCZDYTCJYXQHLXDHYPJQXYLSYYDZOZJNYXQEZYSQYAYXWYPDGXDDXSPPYZNDLTWRHXYDXZZJHTCXMCZLHPYYYYMHZLLHNXMYLLLMDCPPXHMXDKYCYRDLTXJCHHZZXZLCCLYLNZSHZJZZLNNRLWHYQSNJHXYNTTTKYJPYCHHYEGKCTTWLGQRLGGTGTYGYHPYHYLQYQGCWYQKPYYYTTTTLHYHLLTYTTSPLKYZXGZWGPYDSSZZDQXSKCQNMJJZZBXYQMJRTFFBTKHZKBXLJJKDXJTLBWFZPPTKQTZTGPDGNTPJYFALQMKGXBDCLZFHZCLLLLADPMXDJHLCCLGYHDZFGYDDGCYYFGYDXKSSEBDHYKDKDKHNAXXYBPBYYHXZQGAFFQYJXDMLJCSQZLLPCHBSXGJYNDYBYQSPZWJLZKSDDTACTBXZDYZYPJZQSJNKKTKNJDJGYYPGTLFYQKASDNTCYHBLWDZHBBYDWJRYGKZYHEYYFJMSDTYFZJJHGCXPLXHLDWXXJKYTCYKSSSMTWCTTQZLPBSZDZWZXGZAGYKTYWXLHLSPBCLLOQMMZSSLCMBJCSZZKYDCZJGQQDSMCYTZQQLWZQZXSSFPTTFQMDDZDSHDTDWFHTDYZJYQJQKYPBDJYYXTLJHDRQXXXHAYDHRJLKLYTWHLLRLLRCXYLBWSRSZZSYMKZZHHKYHXKSMDSYDYCJPBZBSQLFCXXXNXKXWYWSDZYQOGGQMMYHCDZTTFJYYBGSTTTYBYKJDHKYXBELHTYPJQNFXFDYKZHQKZBYJTZBXHFDXKDASWTAWAJLDYJSFHBLDNNTNQJTJNCHXFJSRFWHZFMDRYJYJWZPDJKZYJYMPCYZNYNXFBYTFYFWYGDBNZZZDNYTXZEMMQBSQEHXFZMBMFLZZSRXYMJGSXWZJSPRYDJSJGXHJJGLJJYNZZJXHGXKYMLPYYYCXYTWQZSWHWLYRJLPXSLSXMFSWWKLCTNXNYNPSJSZHDZEPTXMYYWXYYSYWLXJQZQXZDCLEEELMCPJPCLWBXSQHFWWTFFJTNQJHJQDXHWLBYZNFJLALKYYJLDXHHYCSTYYWNRJYXYWTRMDRQHWQCMFJDYZMHMYYXJWMYZQZXTLMRSPWWCHAQBXYGZYPXYYRRCLMPYMGKSJSZYSRMYJSNXTPLNBAPPYPYLXYYZKYNLDZYJZCZNNLMZHHARQMPGWQTZMXXMLLHGDZXYHXKYXYCJMFFYYHJFSBSSQLXXNDYCANNMTCJCYPRRNYTYQNYYMBMSXNDLYLYSLJRLXYSXQMLLYZLZJJJKYZZCSFBZXXMSTBJGNXYZHLXNMCWSCYZYFZLXBRNNNYLBNRTGZQYSATSWRYHYJZMZDHZGZDWYBSSCSKXSYHYTXXGCQGXZZSHYXJSCRHMKKBXCZJYJYMKQHZJFNBHMQHYSNJNZYBKNQMCLGQHWLZNZSWXKHLJHYYBQLBFCDSXDLDSPFZPSKJYZWZXZDDXJSMMEGJSCSSMGCLXXKYYYLNYPWWWGYDKZJGGGZGGSYCKNJWNJPCXBJJTQTJWDSSPJXZXNZXUMELPXFSXTLLXCLJXJJLJZXCTPSWXLYDHLYQRWHSYCSQYYBYAYWJJJQFWQCQQCJQGXALDBZZYJGKGXPLTZYFXJLTPADKYQHPMATLCPDCKBMTXYBHKLENXDLEEGQDYMSAWHZMLJTWYGXLYQZLJEEYYBQQFFNLYXRDSCTGJGXYYNKLLYQKCCTLHJLQMKKZGCYYGLLLJDZGYDHZWXPYSJBZKDZGYZZHYWYFQYTYZSZYEZZLYMHJJHTSMQWYZLKYYWZCSRKQYTLTDXWCTYJKLWSQZWBDCQYNCJSRSZJLKCDCDTLZZZACQQZZDDXYPLXZBQJYLZLLLQDDZQJYJYJZYXNYYYNYJXKXDAZWYRDLJYYYRJLXLLDYXJCYWYWNQCCLDDNYYYNYCKCZHXXCCLGZQJGKWPPCQQJYSBZZXYJSQPXJPZBSBDSFNSFPZXHDWZTDWPPTFLZZBZDMYYPQJRSDZSQZSQXBDGCPZSWDWCSQZGMDHZXMWWFYBPDGPHTMJTHZSMMBGZMBZJCFZWFZBBZMQCFMBDMCJXLGPNJBBXGYHYYJGPTZGZMQBQTCGYXJXLWZKYDPDYMGCFTPFXYZTZXDZXTGKMTYBBCLBJASKYTSSQYYMSZXFJEWLXLLSZBQJJJAKLYLXLYCCTSXMCWFKKKBSXLLLLJYXTYLTJYYTDPJHNHNNKBYQNFQYYZBYYESSESSGDYHFHWTCJBSDZZTFDMXHCNJZYMQWSRYJDZJQPDQBBSTJGGFBKJBXTGQHNGWJXJGDLLTHZHHYYYYYYSXWTYYYCCBDBPYPZYCCZYJPZYWCBDLFWZCWJDXXHYHLHWZZXJTCZLCDPXUJCZZZLYXJJTXPHFXWPYWXZPTDZZBDZCYHJHMLXBQXSBYLRDTGJRRCTTTHYTCZWMXFYTWWZCWJWXJYWCSKYBZSCCTZQNHXNWXXKHKFHTSWOCCJYBCMPZZYKBNNZPBZHHZDLSYDDYTYFJPXYNGFXBYQXCBHXCPSXTYZDMKYSNXSXLHKMZXLYHDHKWHXXSSKQYHHCJYXGLHZXCSNHEKDTGZXQYPKDHEXTYKCNYMYYYPKQYYYKXZLTHJQTBYQHXBMYHSQCKWWYLLHCYYLNNEQXQWMCFBDCCMLJGGXDQKTLXKGNQCDGZJWYJJLYHHQTTTNWCHMXCXWHWSZJYDJCCDBQCDGDNYXZTHCQRXCBHZTQCBXWGQWYYBXHMBYMYQTYEXMQKYAQYRGYZSLFYKKQHYSSQYSHJGJCNXKZYCXSBXYXHYYLSTYCXQTHYSMGSCPMMGCCCCCMTZTASMGQZJHKLOSQYLSWTMXSYQKDZLJQQYPLSYCZTCQQPBBQJZCLPKHQZYYXXDTDDTSJCXFFLLCHQXMJLWCJCXTSPYCXNDTJSHJWXDQQJSKXYAMYLSJHMLALYKXCYYDMNMDQMXMCZNNCYBZKKYFLMCHCMLHXRCJJHSYLNMTJZGZGYWJXSRXCWJGJQHQZDQJDCJJZKJKGDZQGJJYJYLXZXXCDQHHHEYTMHLFSBDJSYYSHFYSTCZQLPBDRFRZTZYKYWHSZYQKWDQZRKMSYNBCRXQBJYFAZPZZEDZCJYWBCJWHYJBQSZYWRYSZPTDKZPFPBNZTKLQYHBBZPNPPTYZZYBQNYDCPJMMCYCQMCYFZZDCMNLFPBPLNGQJTBTTNJZPZBBZNJKLJQYLNBZQHKSJZNGGQSZZKYXSHPZSNBCGZKDDZQANZHJKDRTLZLSWJLJZLYWTJNDJZJHXYAYNCBGTZCSSQMNJPJYTYSWXZFKWJQTKHTZPLBHSNJZSYZBWZZZZLSYLSBJHDWWQPSLMMFBJDWAQYZTCJTBNNWZXQXCDSLQGDSDPDZHJTQQPSWLYYJZLGYXYZLCTCBJTKTYCZJTQKBSJLGMGZDMCSGPYNJZYQYYKNXRPWSZXMTNCSZZYXYBYHYZAXYWQCJTLLCKJJTJHGDXDXYQYZZBYWDLWQCGLZGJGQRQZCZSSBCRPCSKYDZNXJSQGXSSJMYDNSTZTPBDLTKZWXQWQTZEXNQCZGWEZKSSBYBRTSSSLCCGBPSZQSZLCCGLLLZXHZQTHCZMQGYZQZNMCOCSZJMMZSQPJYGQLJYJPPLDXRGZYXCCSXHSHGTZNLZWZKJCXTCFCJXLBMQBCZZWPQDNHXLJCTHYZLGYLNLSZZPCXDSCQQHJQKSXZPBAJYEMSMJTZDXLCJYRYYNWJBNGZZTMJXLTBSLYRZPYLSSCNXPHLLHYLLQQZQLXYMRSYCXZLMMCZLTZSDWTJJLLNZGGQXPFSKYGYGHBFZPDKMWGHCXMSGDXJMCJZDYCABXJDLNBCDQYGSKYDQTXDJJYXMSZQAZDZFSLQXYJSJZYLBTXXWXQQZBJZUFBBLYLWDSLJHXJYZJWTDJCZFQZQZZDZSXZZQLZCDZFJHYSPYMPQZMLPPLFFXJJNZZYLSJEYQZFPFZKSYWJJJHRDJZZXTXXGLGHYDXCSKYSWMMZCWYBAZBJKSHFHJCXMHFQHYXXYZFTSJYZFXYXPZLCHMZMBXHZZSXYFYMNCWDABAZLXKTCSHHXKXJJZJSTHYGXSXYYHHHJWXKZXSSBZZWHHHCWTZZZPJXSNXQQJGZYZYWLLCWXZFXXYXYHXMKYYSWSQMNLNAYCYSPMJKHWCQHYLAJJMZXHMMCNZHBHXCLXTJPLTXYJHDYYLTTXFSZHYXXSJBJYAYRSMXYPLCKDUYHLXRLNLLSTYZYYQYGYHHSCCSMZCTZQXKYQFPYYRPFFLKQUNTSZLLZMWWTCQQYZWTLLMLMPWMBZSSTZRBPDDTLQJJBXZCSRZQQYGWCSXFWZLXCCRSZDZMCYGGDZQSGTJSWLJMYMMZYHFBJDGYXCCPSHXNZCSBSJYJGJMPPWAFFYFNXHYZXZYLREMZGZCYZSSZDLLJCSQFNXZKPTXZGXJJGFMYYYSNBTYLBNLHPFZDCYFBMGQRRSSSZXYSGTZRNYDZZCDGPJAFJFZKNZBLCZSZPSGCYCJSZLMLRSZBZZLDLSLLYSXSQZQLYXZLSKKBRXBRBZCYCXZZZEEYFGKLZLYYHGZSGZLFJHGTGWKRAAJYZKZQTSSHJJXDCYZUYJLZYRZDQQHGJZXSSZBYKJPBFRTJXLLFQWJHYLQTYMBLPZDXTZYGBDHZZRBGXHWNJTJXLKSCFSMWLSDQYSJTXKZSCFWJLBXFTZLLJZLLQBLSQMQQCGCZFPBPHZCZJLPYYGGDTGWDCFCZQYYYQYSSCLXZSKLZZZGFFCQNWGLHQYZJJCZLQZZYJPJZZBPDCCMHJGXDQDGDLZQMFGPSYTSDYFWWDJZJYSXYYCZCYHZWPBYKXRYLYBHKJKSFXTZJMMCKHLLTNYYMSYXYZPYJQYCSYCWMTJJKQYRHLLQXPSGTLYYCLJSCPXJYZFNMLRGJJTYZBXYZMSJYJHHFZQMSYXRSZCWTLRTQZSSTKXGQKGSPTGCZNJSJCQCXHMXGGZTQYDJKZDLBZSXJLHYQGGGTHQSZPYHJHHGYYGKGGCWJZZYLCZLXQSFTGZSLLLMLJSKCTBLLZZSZMMNYTPZSXQHJCJYQXYZXZQZCPSHKZZYSXCDFGMWQRLLQXRFZTLYSTCTMJCXJJXHJNXTNRZTZFQYHQGLLGCXSZSJDJLJCYDSJTLNYXHSZXCGJZYQPYLFHDJSBPCCZHJJJQZJQDYBSSLLCMYTTMQTBHJQNNYGKYRQYQMZGCJKPDCGMYZHQLLSLLCLMHOLZGDYYFZSLJCQZLYLZQJESHNYLLJXGJXLYSYYYXNBZLJSSZCQQCJYLLZLTJYLLZLLBNYLGQCHXYYXOXCXQKYJXXXYKLXSXXYQXCYKQXQCSGYXXYQXYGYTQOHXHXPYXXXULCYEYCHZZCBWQBBWJQZSCSZSSLZYLKDESJZWMYMCYTSDSXXSCJPQQSQYLYYZYCMDJDZYWCBTJSYDJKCYDDJLBDJJSODZYSYXQQYXDHHGQQYQHDYXWGMMMAJDYBBBPPBCMUUPLJZSMTXERXJMHQNUTPJDCBSSMSSSTKJTSSMMTRCPLZSZMLQDSDMJMQPNQDXCFYNBFSDQXYXHYAYKQYDDLQYYYSSZBYDSLNTFQTZQPZMCHDHCZCWFDXTMYQSPHQYYXSRGJCWTJTZZQMGWJJTJHTQJBBHWZPXXHYQFXXQYWYYHYSCDYDHHQMNMTMWCPBSZPPZZGLMZFOLLCFWHMMSJZTTDHZZYFFYTZZGZYSKYJXQYJZQBHMBZZLYGHGFMSHPZFZSNCLPBQSNJXZSLXXFPMTYJYGBXLLDLXPZJYZJYHHZCYWHJYLSJEXFSZZYWXKZJLUYDTMLYMQJPWXYHXSKTQJEZRPXXZHHMHWQPWQLYJJQJJZSZCPHJLCHHNXJLQWZJHBMZYXBDHHYPZLHLHLGFWLCHYYTLHJXCJMSCPXSTKPNHQXSRTYXXTESYJCTLSSLSTDLLLWWYHDHRJZSFGXTSYCZYNYHTDHWJSLHTZDQDJZXXQHGYLTZPHCSQFCLNJTCLZPFSTPDYNYLGMJLLYCQHYSSHCHYLHQYQTMZYPBYWRFQYKQSYSLZDQJMPXYYSSRHZJNYWTQDFZBWWTWWRXCWHGYHXMKMYYYQMSMZHNGCEPMLQQMTCWCTMMPXJPJJHFXYYZSXZHTYBMSTSYJTTQQQYYLHYNPYQZLCYZHZWSMYLKFJXLWGXYPJYTYSYXYMZCKTTWLKSMZSYLMPWLZWXWQZSSAQSYXYRHSSNTSRAPXCPWCMGDXHXZDZYFJHGZTTSBJHGYZSZYSMYCLLLXBTYXHBBZJKSSDMALXHYCFYGMQYPJYCQXJLLLJGSLZGQLYCJCCZOTYXMTMTTLLWTGPXYMZMKLPSZZZXHKQYSXCTYJZYHXSHYXZKXLZWPSQPYHJWPJPWXQQYLXSDHMRSLZZYZWTTCYXYSZZSHBSCCSTPLWSSCJCHNLCGCHSSPHYLHFHHXJSXYLLNYLSZDHZXYLSXLWZYKCLDYAXZCMDDYSPJTQJZLNWQPSSSWCTSTSZLBLNXSMNYYMJQBQHRZWTYYDCHQLXKPZWBGQYBKFCMZWPZLLYYLSZYDWHXPSBCMLJBSCGBHXLQHYRLJXYSWXWXZSLDFHLSLYNJLZYFLYJYCDRJLFSYZFSLLCQYQFGJYHYXZLYLMSTDJCYHBZLLNWLXXYGYYHSMGDHXXHHLZZJZXCZZZCYQZFNGWPYLCPKPYYPMCLQKDGXZGGWQBDXZZKZFBXXLZXJTPJPTTBYTSZZDWSLCHZHSLTYXHQLHYXXXYYZYSWTXZKHLXZXZPYHGCHKCFSYHUTJRLXFJXPTZTWHPLYXFCRHXSHXKYXXYHZQDXQWULHYHMJTBFLKHTXCWHJFWJCFPQRYQXCYYYQYGRPYWSGSUNGWCHKZDXYFLXXHJJBYZWTSXXNCYJJYMSWZJQRMHXZWFQSYLZJZGBHYNSLBGTTCSYBYXXWXYHXYYXNSQYXMQYWRGYQLXBBZLJSYLPSYTJZYHYZAWLRORJMKSCZJXXXYXCHDYXRYXXJDTSQFXLYLTSFFYXLMTYJMJUYYYXLTZCSXQZQHZXLYYXZHDNBRXXXJCTYHLBRLMBRLLAXKYLLLJLYXXLYCRYLCJTGJCMTLZLLCYZZPZPCYAWHJJFYBDYYZSMPCKZDQYQPBPCJPDCYZMDPBCYYDYCNNPLMTMLRMFMMGWYZBSJGYGSMZQQQZTXMKQWGXLLPJGZBQCDJJJFPKJKCXBLJMSWMDTQJXLDLPPBXCWRCQFBFQJCZAHZGMYKPHYYHZYKNDKZMBPJYXPXYHLFPNYYGXJDBKXNXHJMZJXSTRSTLDXSKZYSYBZXJLXYSLBZYSLHXJPFXPQNBYLLJQKYGZMCYZZYMCCSLCLHZFWFWYXZMWSXTYNXJHPYYMCYSPMHYSMYDYSHQYZCHMJJMZCAAGCFJBBHPLYZYLXXSDJGXDHKXXTXXNBHRMLYJSLTXMRHNLXQJXYZLLYSWQGDLBJHDCGJYQYCMHWFMJYBMBYJYJWYMDPWHXQLDYGPDFXXBCGJSPCKRSSYZJMSLBZZJFLJJJLGXZGYXYXLSZQYXBEXYXHGCXBPLDYHWETTWWCJMBTXCHXYQXLLXFLYXLLJLSSFWDPZSMYJCLMWYTCZPCHQEKCQBWLCQYDPLQPPQZQFJQDJHYMMCXTXDRMJWRHXCJZYLQXDYYNHYYHRSLSRSYWWZJYMTLTLLGTQCJZYABTCKZCJYCCQLJZQXALMZYHYWLWDXZXQDLLQSHGPJFJLJHJABCQZDJGTKHSSTCYJLPSWZLXZXRWGLDLZRLZXTGSLLLLZLYXXWGDZYGBDPHZPBRLWSXQBPFDWOFMWHLYPCBJCCLDMBZPBZZLCYQXLDOMZBLZWPDWYYGDSTTHCSQSCCRSSSYSLFYBFNTYJSZDFNDPDHDZZMBBLSLCMYFFGTJJQWFTMTPJWFNLBZCMMJTGBDZLQLPYFHYYMJYLSDCHDZJWJCCTLJCLDTLJJCPDDSQDSSZYBNDBJLGGJZXSXNLYCYBJXQYCBYLZCFZPPGKCXZDZFZTJJFJSJXZBNZYJQTTYJYHTYCZHYMDJXTTMPXSPLZCDWSLSHXYPZGTFMLCJTYCBPMGDKWYCYZCDSZZYHFLYCTYGWHKJYYLSJCXGYWJCBLLCSNDDBTZBSCLYZCZZSSQDLLMQYYHFSLQLLXFTYHABXGWNYWYYPLLSDLDLLBJCYXJZMLHLJDXYYQYTDLLLBUGBFDFBBQJZZMDPJHGCLGMJJPGAEHHBWCQXAXHHHZCHXYPHJAXHLPHJPGPZJQCQZGJJZZUZDMQYYBZZPHYHYBWHAZYJHYKFGDPFQSDLZMLJXKXGALXZDAGLMDGXMWZQYXXDXXPFDMMSSYMPFMDMMKXKSYZYSHDZKXSYSMMZZZMSYDNZZCZXFPLSTMZDNMXCKJMZTYYMZMZZMSXHHDCZJEMXXKLJSTLWLSQLYJZLLZJSSDPPMHNLZJCZYHMXXHGZCJMDHXTKGRMXFWMCGMWKDTKSXQMMMFZZYDKMSCLCMPCGMHSPXQPZDSSLCXKYXTWLWJYAHZJGZQMCSNXYYMMPMLKJXMHLMLQMXCTKZMJQYSZJSYSZHSYJZJCDAJZYBSDQJZGWZQQXFKDMSDJLFWEHKZQKJPEYPZYSZCDWYJFFMZZYLTTDZZEFMZLBNPPLPLPEPSZALLTYLKCKQZKGENQLWAGYXYDPXLHSXQQWQCQXQCLHYXXMLYCCWLYMQYSKGCHLCJNSZKPYZKCQZQLJPDMDZHLASXLBYDWQLWDNBQCRYDDZTJYBKBWSZDXDTNPJDTCTQDFXQQMGNXECLTTBKPWSLCTYQLPWYZZKLPYGZCQQPLLKCCYLPQMZCZQCLJSLQZDJXLDDHPZQDLJJXZQDXYZQKZLJCYQDYJPPYPQYKJYRMPCBYMCXKLLZLLFQPYLLLMBSGLCYSSLRSYSQTMXYXZQZFDZUYSYZTFFMZZSMZQHZSSCCMLYXWTPZGXZJGZGSJSGKDDHTQGGZLLBJDZLCBCHYXYZHZFYWXYZYMSDBZZYJGTSMTFXQYXQSTDGSLNXDLRYZZLRYYLXQHTXSRTZNGZXBNQQZFMYKMZJBZYMKBPNLYZPBLMCNQYZZZSJZHJCTZKHYZZJRDYZHNPXGLFZTLKGJTCTSSYLLGZRZBBQZZKLPKLCZYSSUYXBJFPNJZZXCDWXZYJXZZDJJKGGRSRJKMSMZJLSJYWQSKYHQJSXPJZZZLSNSHRNYPZTWCHKLPSRZLZXYJQXQKYSJYCZTLQZYBBYBWZPQDWWYZCYTJCJXCKCWDKKZXSGKDZXWWYYJQYYTCYTDLLXWKCZKKLCCLZCQQDZLQLCSFQCHQHSFSMQZZLNBJJZBSJHTSZDYSJQJPDLZCDCWJKJZZLPYCGMZWDJJBSJQZSYZYHHXJPBJYDSSXDZNCGLQMBTSFSBPDZDLZNFGFJGFSMPXJQLMBLGQCYYXBQKDJJQYRFKZTJDHCZKLBSDZCFJTPLLJGXHYXZCSSZZXSTJYGKGCKGYOQXJPLZPBPGTGYJZGHZQZZLBJLSQFZGKQQJZGYCZBZQTLDXRJXBSXXPZXHYZYCLWDXJJHXMFDZPFZHQHQMQGKSLYHTYCGFRZGNQXCLPDLBZCSCZQLLJBLHBZCYPZZPPDYMZZSGYHCKCPZJGSLJLNSCDSLDLXBMSTLDDFJMKDJDHZLZXLSZQPQPGJLLYBDSZGQLBZLSLKYYHZTTNTJYQTZZPSZQZTLLJTYYLLQLLQYZQLBDZLSLYYZYMDFSZSNHLXZNCZQZPBWSKRFBSYZMTHBLGJPMCZZLSTLXSHTCSYZLZBLFEQHLXFLCJLYLJQCBZLZJHHSSTBRMHXZHJZCLXFNBGXGTQJCZTMSFZKJMSSNXLJKBHSJXNTNLZDNTLMSJXGZJYJCZXYJYJWRWWQNZTNFJSZPZSHZJFYRDJSFSZJZBJFZQZZHZLXFYSBZQLZSGYFTZDCSZXZJBQMSZKJRHYJZCKMJKHCHGTXKXQGLXPXFXTRTYLXJXHDTSJXHJZJXZWZLCQSBTXWXGXTXXHXFTSDKFJHZYJFJXRZSDLLLTQSQQZQWZXSYQTWGWBZCGZLLYZBCLMQQTZHZXZXLJFRMYZFLXYSQXXJKXRMQDZDMMYYBSQBHGZMWFWXGMXLZPYYTGZYCCDXYZXYWGSYJYZNBHPZJSQSYXSXRTFYZGRHZTXSZZTHCBFCLSYXZLZQMZLMPLMXZJXSFLBYZMYQHXJSXRXSQZZZSSLYFRCZJRCRXHHZXQYDYHXSJJHZCXZBTYNSYSXJBQLPXZQPYMLXZKYXLXCJLCYSXXZZLXDLLLJJYHZXGYJWKJRWYHCPSGNRZLFZWFZZNSXGXFLZSXZZZBFCSYJDBRJKRDHHGXJLJJTGXJXXSTJTJXLYXQFCSGSWMSBCTLQZZWLZZKXJMLTMJYHSDDBXGZHDLBMYJFRZFSGCLYJBPMLYSMSXLSZJQQHJZFXGFQFQBPXZGYYQXGZTCQWYLTLGWSGWHRLFSFGZJMGMGBGTJFSYZZGZYZAFLSSPMLPFLCWBJZCLJJMZLPJJLYMQDMYYYFBGYGYZMLYZDXQYXRQQQHSYYYQXYLJTYXFSFSLLGNQCYHYCWFHCCCFXPYLYPLLZYXXXXXKQHHXSHJZCFZSCZJXCPZWHHHHHAPYLQALPQAFYHXDYLUKMZQGGGDDESRNNZLTZGCHYPPYSQJJHCLLJTOLNJPZLJLHYMHEYDYDSQYCDDHGZUNDZCLZYZLLZNTNYZGSLHSLPJJBDGWXPCDUTJCKLKCLWKLLCASSTKZZDNQNTTLYYZSSYSSZZRYLJQKCQDHHCRXRZYDGRGCWCGZQFFFPPJFZYNAKRGYWYQPQXXFKJTSZZXSWZDDFBBXTBGTZKZNPZZPZXZPJSZBMQHKCYXYLDKLJNYPKYGHGDZJXXEAHPNZKZTZCMXCXMMJXNKSZQNMNLWBWWXJKYHCPSTMCSQTZJYXTPCTPDTNNPGLLLZSJLSPBLPLQHDTNJNLYYRSZFFJFQWDPHZDWMRZCCLODAXNSSNYZRESTYJWJYJDBCFXNMWTTBYLWSTSZGYBLJPXGLBOCLHPCBJLTMXZLJYLZXCLTPNCLCKXTPZJSWCYXSFYSZDKNTLBYJCYJLLSTGQCBXRYZXBXKLYLHZLQZLNZCXWJZLJZJNCJHXMNZZGJZZXTZJXYCYYCXXJYYXJJXSSSJSTSSTTPPGQTCSXWZDCSYFPTFBFHFBBLZJCLZZDBXGCXLQPXKFZFLSYLTUWBMQJHSZBMDDBCYSCCLDXYCDDQLYJJWMQLLCSGLJJSYFPYYCCYLTJANTJJPWYCMMGQYYSXDXQMZHSZXPFTWWZQSWQRFKJLZJQQYFBRXJHHFWJJZYQAZMYFRHCYYBYQWLPEXCCZSTYRLTTDMQLYKMBBGMYYJPRKZNPBSXYXBHYZDJDNGHPMFSGMWFZMFQMMBCMZZCJJLCNUXYQLMLRYGQZCYXZLWJGCJCGGMCJNFYZZJHYCPRRCMTZQZXHFQGTJXCCJEAQCRJYHPLQLSZDJRBCQHQDYRHYLYXJSYMHZYDWLDFRYHBPYDTSSCNWBXGLPZMLZZTQSSCPJMXXYCSJYTYCGHYCJWYRXXLFEMWJNMKLLSWTXHYYYNCMMCWJDQDJZGLLJWJRKHPZGGFLCCSCZMCBLTBHBQJXQDSPDJZZGKGLFQYWBZYZJLTSTDHQHCTCBCHFLQMPWDSHYYTQWCNZZJTLBYMBPDYYYXSQKXWYYFLXXNCWCXYPMAELYKKJMZZZBRXYYQJFLJPFHHHYTZZXSGQQMHSPGDZQWBWPJHZJDYSCQWZKTXXSQLZYYMYSDZGRXCKKUJLWPYSYSCSYZLRMLQSYLJXBCXTLWDQZPCYCYKPPPNSXFYZJJRCEMHSZMSXLXGLRWGCSTLRSXBZGBZGZTCPLUJLSLYLYMTXMTZPALZXPXJTJWTCYYZLBLXBZLQMYLXPGHDSLSSDMXMBDZZSXWHAMLCZCPJMCNHJYSNSYGCHSKQMZZQDLLKABLWJXSFMOCDXJRRLYQZKJMYBYQLYHETFJZFRFKSRYXFJTWDSXXSYSQJYSLYXWJHSNLXYYXHBHAWHHJZXWMYLJCSSLKYDZTXBZSYFDXGXZJKHSXXYBSSXDPYNZWRPTQZCZENYGCXQFJYKJBZMLJCMQQXUOXSLYXXLYLLJDZBTYMHPFSTTQQWLHOKYBLZZALZXQLHZWRRQHLSTMYPYXJJXMQSJFNBXYXYJXXYQYLTHYLQYFMLKLJTMLLHSZWKZHLJMLHLJKLJSTLQXYLMBHHLNLZXQJHXCFXXLHYHJJGBYZZKBXSCQDJQDSUJZYYHZHHMGSXCSYMXFEBCQWWRBPYYJQTYZCYQYQQZYHMWFFHGZFRJFCDPXNTQYZPDYKHJLFRZXPPXZDBBGZQSTLGDGYLCQMLCHHMFYWLZYXKJLYPQHSYWMQQGQZMLZJNSQXJQSYJYCBEHSXFSZPXZWFLLBCYYJDYTDTHWZSFJMQQYJLMQXXLLDTTKHHYBFPWTYYSQQWNQWLGWDEBZWCMYGCULKJXTMXMYJSXHYBRWFYMWFRXYQMXYSZTZZTFYKMLDHQDXWYYNLCRYJBLPSXCXYWLSPRRJWXHQYPHTYDNXHHMMYWYTZCSQMTSSCCDALWZTCPQPYJLLQZYJSWXMZZMMYLMXCLMXCZMXMZSQTZPPQQBLPGXQZHFLJJHYTJSRXWZXSCCDLXTYJDCQJXSLQYCLZXLZZXMXQRJMHRHZJBHMFLJLMLCLQNLDXZLLLPYPSYJYSXCQQDCMQJZZXHNPNXZMEKMXHYKYQLXSXTXJYYHWDCWDZHQYYBGYBCYSCFGPSJNZDYZZJZXRZRQJJYMCANYRJTLDPPYZBSTJKXXZYPFDWFGZZRPYMTNGXZQBYXNBUFNQKRJQZMJEGRZGYCLKXZDSKKNSXKCLJSPJYYZLQQJYBZSSQLLLKJXTBKTYLCCDDBLSPPFYLGYDTZJYQGGKQTTFZXBDKTYYHYBBFYTYYBCLPDYTGDHRYRNJSPTCSNYJQHKLLLZSLYDXXWBCJQSPXBPJZJCJDZFFXXBRMLAZHCSNDLBJDSZBLPRZTSWSBXBCLLXXLZDJZSJPYLYXXYFTFFFBHJJXGBYXJPMMMPSSJZJMTLYZJXSWXTYLEDQPJMYGQZJGDJLQJWJQLLSJGJGYGMSCLJJXDTYGJQJQJCJZCJGDZZSXQGSJGGCXHQXSNQLZZBXHSGZXCXYLJXYXYYDFQQJHJFXDHCTXJYRXYSQTJXYEFYYSSYYJXNCYZXFXMSYSZXYYSCHSHXZZZGZZZGFJDLTYLNPZGYJYZYYQZPBXQBDZTZCZYXXYHHSQXSHDHGQHJHGYWSZTMZMLHYXGEBTYLZKQWYTJZRCLEKYSTDBCYKQQSAYXCJXWWGSBHJYZYDHCSJKQCXSWXFLTYNYZPZCCZJQTZWJQDZZZQZLJJXLSBHPYXXPSXSHHEZTXFPTLQYZZXHYTXNCFZYYHXGNXMYWXTZSJPTHHGYMXMXQZXTSBCZYJYXXTYYZYPCQLMMSZMJZZLLZXGXZAAJZYXJMZXWDXZSXZDZXLEYJJZQBHZWZZZQTZPSXZTDSXJJJZNYAZPHXYYSRNQDTHZHYYKYJHDZXZLSWCLYBZYECWCYCRYLCXNHZYDZYDYJDFRJJHTRSQTXYXJRJHOJYNXELXSFSFJZGHPZSXZSZDZCQZBYYKLSGSJHCZSHDGQGXYZGXCHXZJWYQWGYHKSSEQZZNDZFKWYSSTCLZSTSYMCDHJXXYWEYXCZAYDMPXMDSXYBSQMJMZJMTZQLPJYQZCGQHXJHHLXXHLHDLDJQCLDWBSXFZZYYSCHTYTYYBHECXHYKGJPXHHYZJFXHWHBDZFYZBCAPNPGNYDMSXHMMMMAMYNBYJTMPXYYMCTHJBZYFCGTYHWPHFTWZZEZSBZEGPFMTSKFTYCMHFLLHGPZJXZJGZJYXZSBBQSCZZLZCCSTPGXMJSFTCCZJZDJXCYBZLFCJSYZFGSZLYBCWZZBYZDZYPSWYJZXZBDSYUXLZZBZFYGCZXBZHZFTPBGZGEJBSTGKDMFHYZZJHZLLZZGJQZLSFDJSSCBZGPDLFZFZSZYZYZSYGCXSNXXCHCZXTZZLJFZGQSQYXZJQDCCZTQCDXZJYQJQCHXZTDLGSCXZSYQJQTZWLQDQZTQCHQQJZYEZZZPBWKDJFCJPZTYPQYQTTYNLMBDKTJZPQZQZZFPZSBNJLGYJDXJDZZKZGQKXDLPZJTCJDQBXDJQJSTCKNXBXZMSLYJCQMTJQWWCJQNJNLLLHJCWQTBZQYDZCZPZZDZYDDCYZZZCCJTTJFZDPRRTZTJDCQTQZDTJNPLZBCLLCTZSXKJZQZPZLBZRBTJDCXFCZDBCCJJLTQQPLDCGZDBBZJCQDCJWYNLLZYZCCDWLLXWZLXRXNTQQCZXKQLSGDFQTDDGLRLAJJTKUYMKQLLTZYTDYYCZGJWYXDXFRSKSTQTENQMRKQZHHQKDLDAZFKYPBGGPZREBZZYKZZSPEGJXGYKQZZZSLYSYYYZWFQZYLZZLZHWCHKYPQGNPGBLPLRRJYXCCSYYHSFZFYBZYYTGZXYLXCZWXXZJZBLFFLGSKHYJZEYJHLPLLLLCZGXDRZELRHGKLZZYHZLYQSZZJZQLJZFLNBHGWLCZCFJYSPYXZLZLXGCCPZBLLCYBBBBUBBCBPCRNNZCZYRBFSRLDCGQYYQXYGMQZWTZYTYJXYFWTEHZZJYWLCCNTZYJJZDEDPZDZTSYQJHDYMBJNYJZLXTSSTPHNDJXXBYXQTZQDDTJTDYYTGWSCSZQFLSHLGLBCZPHDLYZJYCKWTYTYLBNYTSDSYCCTYSZYYEBHEXHQDTWNYGYCLXTSZYSTQMYGZAZCCSZZDSLZCLZRQXYYELJSBYMXSXZTEMBBLLYYLLYTDQYSHYMRQWKFKBFXNXSBYCHXBWJYHTQBPBSBWDZYLKGZSKYHXQZJXHXJXGNLJKZLYYCDXLFYFGHLJGJYBXQLYBXQPQGZTZPLNCYPXDJYQYDYMRBESJYYHKXXSTMXRCZZYWXYQYBMCLLYZHQYZWQXDBXBZWZMSLPDMYSKFMZKLZCYQYCZLQXFZZYDQZPZYGYJYZMZXDZFYFYTTQTZHGSPCZMLCCYTZXJCYTJMKSLPZHYSNZLLYTPZCTZZCKTXDHXXTQCYFKSMQCCYYAZHTJPCYLZLYJBJXTPNYLJYYNRXSYLMMNXJSMYBCSYSYLZYLXJJQYLDZLPQBFZZBLFNDXQKCZFYWHGQMRDSXYCYTXNQQJZYYPFZXDYZFPRXEJDGYQBXRCNFYYQPGHYJDYZXGRHTKYLNWDZNTSMPKLBTHBPYSZBZTJZSZZJTYYXZPHSSZZBZCZPTQFZMYFLYPYBBJQXZMXXDJMTSYSKKBJZXHJCKLPSMKYJZCXTMLJYXRZZQSLXXQPYZXMKYXXXJCLJPRMYYGADYSKQLSNDHYZKQXZYZTCGHZTLMLWZYBWSYCTBHJHJFCWZTXWYTKZLXQSHLYJZJXTMPLPYCGLTBZZTLZJCYJGDTCLKLPLLQPJMZPAPXYZLKKTKDZCZZBNZDYDYQZJYJGMCTXLTGXSZLMLHBGLKFWNWZHDXUHLFMKYSLGXDTWWFRJEJZTZHYDXYKSHWFZCQSHKTMQQHTZHYMJDJSKHXZJZBZZXYMPAGQMSTPXLSKLZYNWRTSQLSZBPSPSGZWYHTLKSSSWHZZLYYTNXJGMJSZSUFWNLSOZTXGXLSAMMLBWLDSZYLAKQCQCTMYCFJBSLXCLZZCLXXKSBZQCLHJPSQPLSXXCKSLNHPSFQQYTXYJZLQLDXZQJZDYYDJNZPTUZDSKJFSLJHYLZSQZLBTXYDGTQFDBYAZXDZHZJNHHQBYKNXJJQCZMLLJZKSPLDYCLBBLXKLELXJLBQYCXJXGCNLCQPLZLZYJTZLJGYZDZPLTQCSXFDMNYCXGBTJDCZNBGBQYQJWGKFHTNPYQZQGBKPBBYZMTJDYTBLSQMPSXTBNPDXKLEMYYCJYNZCTLDYKZZXDDXHQSHDGMZSJYCCTAYRZLPYLTLKXSLZCGGEXCLFXLKJRTLQJAQZNCMBYDKKCXGLCZJZXJHPTDJJMZQYKQSECQZDSHHADMLZFMMZBGNTJNNLGBYJBRBTMLBYJDZXLCJLPLDLPCQDHLXZLYCBLCXZZJADJLNZMMSSSMYBHBSQKBHRSXXJMXSDZNZPXLGBRHWGGFCXGMSKLLTSJYYCQLTSKYWYYHYWXBXQYWPYWYKQLSQPTNTKHQCWDQKTWPXXHCPTHTWUMSSYHBWCRWXHJMKMZNGWTMLKFGHKJYLSYYCXWHYECLQHKQHTTQKHFZLDXQWYZYYDESBPKYRZPJFYYZJCEQDZZDLATZBBFJLLCXDLMJSSXEGYGSJQXCWBXSSZPDYZCXDNYXPPZYDLYJCZPLTXLSXYZYRXCYYYDYLWWNZSAHJSYQYHGYWWAXTJZDAXYSRLTDPSSYYFNEJDXYZHLXLLLZQZSJNYQYQQXYJGHZGZCYJCHZLYCDSHWSHJZYJXCLLNXZJJYYXNFXMWFPYLCYLLABWDDHWDXJMCXZTZPMLQZHSFHZYNZTLLDYWLSLXHYMMYLMBWWKYXYADTXYLLDJPYBPWUXJMWMLLSAFDLLYFLBHHHBQQLTZJCQJLDJTFFKMMMBYTHYGDCQRDDWRQJXNBYSNWZDBYYTBJHPYBYTTJXAAHGQDQTMYSTQXKBTZPKJLZRBEQQSSMJJBDJOTGTBXPGBKTLHQXJJJCTHXQDWJLWRFWQGWSHCKRYSWGFTGYGBXSDWDWRFHWYTJJXXXJYZYSLPYYYPAYXHYDQKXSHXYXGSKQHYWFDDDPPLCJLQQEEWXKSYYKDYPLTJTHKJLTCYYHHJTTPLTZZCDLTHQKZXQYSTEEYWYYZYXXYYSTTJKLLPZMCYHQGXYHSRMBXPLLNQYDQHXSXXWGDQBSHYLLPJJJTHYJKYPPTHYYKTYEZYENMDSHLCRPQFDGFXZPSFTLJXXJBSWYYSKSFLXLPPLBBBLBSFXFYZBSJSSYLPBBFFFFSSCJDSTZSXZRYYSYFFSYZYZBJTBCTSBSDHRTJJBYTCXYJEYLXCBNEBJDSYXYKGSJZBXBYTFZWGENYHHTHZHHXFWGCSTBGXKLSXYWMTMBYXJSTZSCDYQRCYTWXZFHMYMCXLZNSDJTTTXRYCFYJSBSDYERXJLJXBBDEYNJGHXGCKGSCYMBLXJMSZNSKGXFBNBPTHFJAAFXYXFPXMYPQDTZCXZZPXRSYWZDLYBBKTYQPQJPZYPZJZNJPZJLZZFYSBTTSLMPTZRTDXQSJEHBZYLZDHLJSQMLHTXTJECXSLZZSPKTLZKQQYFSYGYWPCPQFHQHYTQXZKRSGTTSQCZLPTXCDYYZXSQZSLXLZMYCPCQBZYXHBSXLZDLTCDXTYLZJYYZPZYZLTXJSJXHLPMYTXCQRBLZSSFJZZTNJYTXMYJHLHPPLCYXQJQQKZZSCPZKSWALQSBLCCZJSXGWWWYGYKTJBBZTDKHXHKGTGPBKQYSLPXPJCKBMLLXDZSTBKLGGQKQLSBKKTFXRMDKBFTPZFRTBBRFERQGXYJPZSSTLBZTPSZQZSJDHLJQLZBPMSMMSXLQQNHKNBLRDDNXXDHDDJCYYGYLXGZLXSYGMQQGKHBPMXYXLYTQWLWGCPBMQXCYZYDRJBHTDJYHQSHTMJSBYPLWHLZFFNYPMHXXHPLTBQPFBJWQDBYGPNZTPFZJGSDDTQSHZEAWZZYLLTYYBWJKXXGHLFKXDJTMSZSQYNZGGSWQSPHTLSSKMCLZXYSZQZXNCJDQGZDLFNYKLJCJLLZLMZZNHYDSSHTHZZLZZBBHQZWWYCRZHLYQQJBEYFXXXWHSRXWQHWPSLMSSKZTTYGYQQWRSLALHMJTQJSMXQBJJZJXZYZKXBYQXBJXSHZTSFJLXMXZXFGHKZSZGGYLCLSARJYHSLLLMZXELGLXYDJYTLFBHBPNLYZFBBHPTGJKWETZHKJJXZXXGLLJLSTGSHJJYQLQZFKCGNNDJSSZFDBCTWWSEQFHQJBSAQTGYPQLBXBMMYWXGSLZHGLZGQYFLZBYFZJFRYSFMBYZHQGFWZSYFYJJPHZBYYZFFWODGRLMFTWLBZGYCQXCDJYGZYYYYTYTYDWEGAZYHXJLZYYHLRMGRXXZCLHNELJJTJTPWJYBJJBXJJTJTEEKHWSLJPLPSFYZPQQBDLQJJTYYQLYZKDKSQJYYQZLDQTGJQYZJSUCMRYQTHTEJMFCTYHYPKMHYZWJDQFHYYXWSHCTXRLJHQXHCCYYYJLTKTTYTMXGTCJTZAYYOCZLYLBSZYWJYTSJYHBYSHFJLYGJXXTMZYYLTXXYPZLXYJZYZYYPNHMYMDYYLBLHLSYYQQLLNJJYMSOYQBZGDLYXYLCQYXTSZEGXHZGLHWBLJHEYXTWQMAKBPQCGYSHHEGQCMWYYWLJYJHYYZLLJJYLHZYHMGSLJLJXCJJYCLYCJPCPZJZJMMYLCQLNQLJQJSXYJMLSZLJQLYCMMHCFMMFPQQMFYLQMCFFQMMMMHMZNFHHJGTTHHKHSLNCHHYQDXTMMQDCYZYXYQMYQYLTDCYYYZAZZCYMZYDLZFFFMMYCQZWZZMABTBYZTDMNZZGGDFTYPCGQYTTSSFFWFDTZQSSYSTWXJHXYTSXXYLBYQHWWKXHZXWZNNZZJZJJQJCCCHYYXBZXZCYZTLLCQXYNJYCYYCYNZZQYYYEWYCZDCJYCCHYJLBTZYYCQWMPWPYMLGKDLDLGKQQBGYCHJXY";
-
- // 此处收录了375个多音字
- string multiPinyin = "19969:DZ,19975:WM,19988:QJ,20048:YL,20056:SC,20060:NM,20094:QG,20127:QJ,20167:QC,20193:YG,20250:KH,20256:ZC,20282:SC,20285:QJG,20291:TD,20314:YD,20340:NE,20375:TD,20389:YJ,20391:CZ,20415:PB,20446:YS,20447:SQ,20504:TC,20608:KG,20854:QJ,20857:ZC,20911:PF,20504:TC,20608:KG,20854:QJ,20857:ZC,20911:PF,20985:AW,21032:PB,21048:XQ,21049:SC,21089:YS,21119:JC,21242:SB,21273:SC,21305:YP,21306:QO,21330:ZC,21333:SDC,21345:QK,21378:CA,21397:SC,21414:XS,21442:SC,21477:JG,21480:TD,21484:ZS,21494:YX,21505:YX,21512:HG,21523:XH,21537:PB,21542:PF,21549:KH,21571:E,21574:DA,21588:TD,21589:O,21618:ZC,21621:KHA,21632:ZJ,21654:KG,21679:LKG,21683:KH,21710:A,21719:YH,21734:WOE,21769:A,21780:WN,21804:XH,21834:A,21899:ZD,21903:RN,21908:WO,21939:ZC,21956:SA,21964:YA,21970:TD,22003:A,22031:JG,22040:XS,22060:ZC,22066:ZC,22079:MH,22129:XJ,22179:XA,22237:NJ,22244:TD,22280:JQ,22300:YH,22313:XW,22331:YQ,22343:YJ,22351:PH,22395:DC,22412:TD,22484:PB,22500:PB,22534:ZD,22549:DH,22561:PB,22612:TD,22771:KQ,22831:HB,22841:JG,22855:QJ,22865:XQ,23013:ML,23081:WM,23487:SX,23558:QJ,23561:YW,23586:YW,23614:YW,23615:SN,23631:PB,23646:ZS,23663:ZT,23673:YG,23762:TD,23769:ZS,23780:QJ,23884:QK,24055:XH,24113:DC,24162:ZC,24191:GA,24273:QJ,24324:NL,24377:TD,24378:QJ,24439:PF,24554:ZS,24683:TD,24694:WE,24733:LK,24925:TN,25094:ZG,25100:XQ,25103:XH,25153:PB,25170:PB,25179:KG,25203:PB,25240:ZS,25282:FB,25303:NA,25324:KG,25341:ZY,25373:WZ,25375:XJ,25384:A,25457:A,25528:SD,25530:SC,25552:TD,25774:ZC,25874:ZC,26044:YW,26080:WM,26292:PB,26333:PB,26355:ZY,26366:CZ,26397:ZC,26399:QJ,26415:ZS,26451:SB,26526:ZC,26552:JG,26561:TD,26588:JG,26597:CZ,26629:ZS,26638:YL,26646:XQ,26653:KG,26657:XJ,26727:HG,26894:ZC,26937:ZS,26946:ZC,26999:KJ,27099:KJ,27449:YQ,27481:XS,27542:ZS,27663:ZS,27748:TS,27784:SC,27788:ZD,27795:TD,27812:O,27850:PB,27852:MB,27895:SL,27898:PL,27973:QJ,27981:KH,27986:HX,27994:XJ,28044:YC,28065:WG,28177:SM,28267:QJ,28291:KH,28337:ZQ,28463:TL,28548:DC,28601:TD,28689:PB,28805:JG,28820:QG,28846:PB,28952:TD,28975:ZC,29100:A,29325:QJ,29575:SL,29602:FB,30010:TD,30044:CX,30058:PF,30091:YSP,30111:YN,30229:XJ,30427:SC,30465:SX,30631:YQ,30655:QJ,30684:QJG,30707:SD,30729:XH,30796:LG,30917:PB,31074:NM,31085:JZ,31109:SC,31181:ZC,31192:MLB,31293:JQ,31400:YX,31584:YJ,31896:ZN,31909:ZY,31995:XJ,32321:PF,32327:ZY,32418:HG,32420:XQ,32421:HG,32438:LG,32473:GJ,32488:TD,32521:QJ,32527:PB,32562:ZSQ,32564:JZ,32735:ZD,32793:PB,33071:PF,33098:XL,33100:YA,33152:PB,33261:CX,33324:BP,33333:TD,33406:YA,33426:WM,33432:PB,33445:JG,33486:ZN,33493:TS,33507:QJ,33540:QJ,33544:ZC,33564:XQ,33617:YT,33632:QJ,33636:XH,33637:YX,33694:WG,33705:PF,33728:YW,33882:SR,34067:WM,34074:YW,34121:QJ,34255:ZC,34259:XL,34425:JH,34430:XH,34485:KH,34503:YS,34532:HG,34552:XS,34558:YE,34593:ZL,34660:YQ,34892:XH,34928:SC,34999:QJ,35048:PB,35059:SC,35098:ZC,35203:TQ,35265:JX,35299:JX,35782:SZ,35828:YS,35830:E,35843:TD,35895:YG,35977:MH,36158:JG,36228:QJ,36426:XQ,36466:DC,36710:JC,36711:ZYG,36767:PB,36866:SK,36951:YW,37034:YX,37063:XH,37218:ZC,37325:ZC,38063:PB,38079:TD,38085:QY,38107:DC,38116:TD,38123:YD,38224:HG,38241:XTC,38271:ZC,38415:YE,38426:KH,38461:YD,38463:AE,38466:PB,38477:XJ,38518:YT,38551:WK,38585:ZC,38704:XS,38739:LJ,38761:GJ,38808:SQ,39048:JG,39049:XJ,39052:HG,39076:CZ,39271:XT,39534:TD,39552:TD,39584:PB,39647:SB,39730:LG,39748:TPB,40109:ZQ,40479:ND,40516:HG,40536:HG,40583:QJ,40765:YQ,40784:QJ,40840:YK,40863:QJG,";
- string resStr = string.Empty;
- int i, j, uni;
- uni = HanZi;
- if (uni > 40869 || uni < 19968)
- return resStr;
-
- // 返回该字符在Unicode字符集中的编码值
- i = multiPinyin.IndexOf(uni.ToString());
-
- // 检查是否是多音字,是按多音字处理,不是就直接在strChineseFirstPY字符串中找对应的首字母
- if (i < 0)
- {
- // 获取非多音字汉字首字母
- resStr = strChineseFirstPY[uni - 19968].ToString();
- }
- else
- {
- // 获取多音字汉字首字母
- j = multiPinyin.IndexOf(",", i);
- resStr = multiPinyin.Substring(i + 6, j - i - 6);
- }
-
- return resStr;
- }
- #endregion
-
- #region 汉字转换成全拼的拼音
+ #region 汉字转换成全拼的拼音
///
/// 汉字转换成全拼的拼音.
@@ -191,81 +191,81 @@ public class PinyinHelper
"Zhuang", "Zhui", "Zhun", "Zhuo", "Zi", "Zong", "Zou", "Zu", "Zuan", "Zui", "Zun", "Zuo"
};
- // 验证是否输入汉字
- Regex reg = new Regex("^[\u4e00-\u9fa5]$");
- byte[] arr = new byte[2];
- string pystr = string.Empty;
- int asc = 0, M1 = 0, M2 = 0;
+ // 验证是否输入汉字
+ Regex reg = new Regex("^[\u4e00-\u9fa5]$");
+ byte[] arr = new byte[2];
+ string pystr = string.Empty;
+ int asc = 0, M1 = 0, M2 = 0;
- // 获取汉字对应的字符数组
- char[] mChar = Chstr.ToCharArray();
- for (int j = 0; j < mChar.Length; j++)
- {
- // 如果输入的是汉字
- if (reg.IsMatch(mChar[j].ToString()))
- {
- arr = System.Text.Encoding.Default.GetBytes(mChar[j].ToString());
- M1 = (short)arr[0];
- M2 = (short)arr[1];
- asc = (M1 * 256) + M2 - 65536;
- if (asc > 0 && asc < 160)
+ // 获取汉字对应的字符数组
+ char[] mChar = Chstr.ToCharArray();
+ for (int j = 0; j < mChar.Length; j++)
{
- pystr += mChar[j];
- }
- else
- {
- switch (asc)
- {
- case -9254:
- pystr += "Zhen"; break;
- case -8985:
- pystr += "Qian"; break;
- case -5463:
- pystr += "Jia"; break;
- case -8274:
- pystr += "Ge"; break;
- case -5448:
- pystr += "Ga"; break;
- case -5447:
- pystr += "La"; break;
- case -4649:
- pystr += "Chen"; break;
- case -5436:
- pystr += "Mao"; break;
- case -5213:
- pystr += "Mao"; break;
- case -3597:
- pystr += "Die"; break;
- case -5659:
- pystr += "Tian"; break;
- default:
- for (int i = getValue.Length - 1; i >= 0; i--)
- {
- // 判断汉字的拼音区编码是否在指定范围内
- if (getValue[i] <= asc)
+ // 如果输入的是汉字
+ if (reg.IsMatch(mChar[j].ToString()))
+ {
+ arr = System.Text.Encoding.Default.GetBytes(mChar[j].ToString());
+ M1 = (short)arr[0];
+ M2 = (short)arr[1];
+ asc = (M1 * 256) + M2 - 65536;
+ if (asc > 0 && asc < 160)
{
- // 如果不超出范围则获取对应的拼音
- pystr += getName[i];
- break;
+ pystr += mChar[j];
}
- }
+ else
+ {
+ switch (asc)
+ {
+ case -9254:
+ pystr += "Zhen"; break;
+ case -8985:
+ pystr += "Qian"; break;
+ case -5463:
+ pystr += "Jia"; break;
+ case -8274:
+ pystr += "Ge"; break;
+ case -5448:
+ pystr += "Ga"; break;
+ case -5447:
+ pystr += "La"; break;
+ case -4649:
+ pystr += "Chen"; break;
+ case -5436:
+ pystr += "Mao"; break;
+ case -5213:
+ pystr += "Mao"; break;
+ case -3597:
+ pystr += "Die"; break;
+ case -5659:
+ pystr += "Tian"; break;
+ default:
+ for (int i = getValue.Length - 1; i >= 0; i--)
+ {
+ // 判断汉字的拼音区编码是否在指定范围内
+ if (getValue[i] <= asc)
+ {
+ // 如果不超出范围则获取对应的拼音
+ pystr += getName[i];
+ break;
+ }
+ }
- break;
- }
+ break;
+ }
+ }
+ }
+
+ // 如果不是汉字
+ else
+ {
+ // 如果不是汉字则返回
+ pystr += mChar[j].ToString();
+ }
}
- }
- // 如果不是汉字
- else
- {
- // 如果不是汉字则返回
- pystr += mChar[j].ToString();
- }
+ // 返回获取到的汉字拼音
+ return pystr;
}
- // 返回获取到的汉字拼音
- return pystr;
- }
-
- #endregion
+ #endregion
}
\ No newline at end of file
diff --git a/common/Tnb.Common/Security/SuperQueryHelper.cs b/common/Tnb.Common/Security/SuperQueryHelper.cs
index e42973c6..337aa93b 100644
--- a/common/Tnb.Common/Security/SuperQueryHelper.cs
+++ b/common/Tnb.Common/Security/SuperQueryHelper.cs
@@ -60,7 +60,23 @@ public class SuperQueryHelper
{
case JnpfKeyConst.COMINPUT:
case JnpfKeyConst.TEXTAREA:
- item.fieldValue = item.fieldValue?.ToString()?.Replace("\r\n", string.Empty);
+ case JnpfKeyConst.CHECKBOX:
+ case JnpfKeyConst.SELECT:
+ case JnpfKeyConst.TIME:
+ case JnpfKeyConst.DEPSELECT:
+ case JnpfKeyConst.GROUPSELECT:
+ case JnpfKeyConst.POSSELECT:
+ case JnpfKeyConst.USERSELECT:
+ case JnpfKeyConst.ROLESELECT:
+ case JnpfKeyConst.TREESELECT:
+ case JnpfKeyConst.RELATIONFORM:
+ case JnpfKeyConst.RELATIONFORMATTR:
+ case JnpfKeyConst.POPUPSELECT:
+ case JnpfKeyConst.POPUPATTR:
+ case JnpfKeyConst.CALCULATE:
+ case JnpfKeyConst.CREATEUSER:
+ case JnpfKeyConst.MODIFYUSER:
+ item.fieldValue = item.fieldValue?.ToString().Replace("\r\n", string.Empty);
switch (item.symbol)
{
case "==": // 等于
@@ -91,228 +107,13 @@ public class SuperQueryHelper
queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
switch (item.symbol)
{
- case "like": // 包含
- conditionalType = ConditionalType.NoLike;
- break;
case "notLike": // 不包含
- conditionalType = ConditionalType.Like;
- break;
case "<>": // 不等于
conditionalType = ConditionalType.IsNullOrEmpty;
queryList.Add(ControlAdvancedQueryAssembly(WhereType.Or, item.jnpfKey, field, null, conditionalType));
break;
}
break;
- case JnpfKeyConst.NUMINPUT:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.SWITCH:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.RADIO:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.CHECKBOX:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.SELECT:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.POPUPTABLESELECT:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.CASCADER:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
case JnpfKeyConst.DATE:
switch (item.symbol)
{
@@ -326,7 +127,7 @@ public class SuperQueryHelper
conditionalType = ConditionalType.Equal;
break;
case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
+ conditionalType = ConditionalType.LessThanOrEqual;
break;
case "<": // 小于
conditionalType = ConditionalType.LessThan;
@@ -335,15 +136,23 @@ public class SuperQueryHelper
conditionalType = ConditionalType.NoEqual;
break;
case "like": // 包含
- conditionalType = ConditionalType.Like;
+ conditionalType = ConditionalType.Equal;
break;
case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
+ conditionalType = ConditionalType.NoEqual;
+ break;
+ }
+ queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ToObject().ToString(), conditionalType, true));
+ switch (item.symbol)
+ {
+ case "notLike": // 不包含
+ case "<>": // 不等于
+ conditionalType = ConditionalType.IsNullOrEmpty;
+ queryList.Add(ControlAdvancedQueryAssembly(WhereType.Or, item.jnpfKey, field, null, conditionalType));
break;
}
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
break;
- case JnpfKeyConst.TIME:
+ case JnpfKeyConst.CREATETIME:
switch (item.symbol)
{
case ">=": // 大于等于
@@ -356,7 +165,7 @@ public class SuperQueryHelper
conditionalType = ConditionalType.Equal;
break;
case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
+ conditionalType = ConditionalType.LessThan;
break;
case "<": // 小于
conditionalType = ConditionalType.LessThan;
@@ -365,15 +174,68 @@ public class SuperQueryHelper
conditionalType = ConditionalType.NoEqual;
break;
case "like": // 包含
- conditionalType = ConditionalType.Like;
+ conditionalType = ConditionalType.Equal;
break;
case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
+ conditionalType = ConditionalType.NoEqual;
+ break;
+ }
+ queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, string.Format("{0:yyyy-MM-dd HH:mm:ss}", item.fieldValue.ToObject()), conditionalType, true));
+ switch (item.symbol)
+ {
+ case "notLike": // 不包含
+ case "<>": // 不等于
+ conditionalType = ConditionalType.IsNullOrEmpty;
+ queryList.Add(ControlAdvancedQueryAssembly(WhereType.Or, item.jnpfKey, field, null, conditionalType));
break;
}
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
break;
+ case JnpfKeyConst.MODIFYTIME:
+ switch (item.symbol)
+ {
+ case ">=": // 大于等于
+ conditionalType = ConditionalType.GreaterThanOrEqual;
+ break;
+ case ">": // 大于
+ conditionalType = ConditionalType.GreaterThan;
+ break;
+ case "==": // 等于
+ conditionalType = ConditionalType.Equal;
+ break;
+ case "<=": // 小于等于
+ conditionalType = ConditionalType.LessThanOrEqual;
+ break;
+ case "<": // 小于
+ conditionalType = ConditionalType.LessThan;
+ break;
+ case "<>": // 不等于
+ conditionalType = ConditionalType.NoEqual;
+ break;
+ case "like": // 包含
+ conditionalType = ConditionalType.Equal;
+ break;
+ case "notLike": // 不包含
+ conditionalType = ConditionalType.NoEqual;
+ break;
+ }
+ queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, string.Format("{0:yyyy-MM-dd HH:mm:ss}", item.fieldValue.ToObject()), conditionalType, true));
+ switch (item.symbol)
+ {
+ case "notLike": // 不包含
+ case "<>": // 不等于
+ conditionalType = ConditionalType.IsNullOrEmpty;
+ queryList.Add(ControlAdvancedQueryAssembly(WhereType.Or, item.jnpfKey, field, null, conditionalType));
+ break;
+ }
+ break;
+ case JnpfKeyConst.NUMINPUT:
+ case JnpfKeyConst.SWITCH:
+ case JnpfKeyConst.RADIO:
+ case JnpfKeyConst.POPUPTABLESELECT:
case JnpfKeyConst.COMSELECT:
+ case JnpfKeyConst.BILLRULE:
+ case JnpfKeyConst.CURRDEPT:
+ case JnpfKeyConst.CURRPOSITION:
switch (item.symbol)
{
case ">=": // 大于等于
@@ -386,97 +248,7 @@ public class SuperQueryHelper
conditionalType = ConditionalType.Equal;
break;
case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.DEPSELECT:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.POSSELECT:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.USERSELECT:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
+ conditionalType = ConditionalType.LessThanOrEqual;
break;
case "<": // 小于
conditionalType = ConditionalType.LessThan;
@@ -494,6 +266,8 @@ public class SuperQueryHelper
queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
break;
case JnpfKeyConst.USERSSELECT:
+ if (item.symbol.Equals("==")) item.symbol = "like";
+ if (item.symbol.Equals("<>")) item.symbol = "notLike";
if (item.fieldValue != null && (item.symbol.Equals("like") || item.symbol.Equals("notLike")))
{
var rIdList = GetUserRelationByUserId(item.fieldValue.ToString());
@@ -549,159 +323,10 @@ public class SuperQueryHelper
queryOr.mainWhere = true;
queryList.Add(queryOr);
}
- //modified by PhilPan
- continue;
}
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.ROLESELECT:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.GROUPSELECT:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.TREESELECT:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.BILLRULE:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
+ continue;
case JnpfKeyConst.ADDRESS:
+ case JnpfKeyConst.CASCADER:
switch (item.symbol)
{
case ">=": // 大于等于
@@ -712,266 +337,39 @@ public class SuperQueryHelper
break;
case "==": // 等于
conditionalType = ConditionalType.Equal;
+ item.fieldValue = item.fieldValue.ToObject>().ToJsonString();
break;
case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
+ conditionalType = ConditionalType.LessThanOrEqual;
break;
case "<": // 小于
conditionalType = ConditionalType.LessThan;
break;
case "<>": // 不等于
conditionalType = ConditionalType.NoEqual;
+ item.fieldValue = item.fieldValue.ToObject>().ToJsonString();
break;
case "like": // 包含
conditionalType = ConditionalType.Like;
+ item.fieldValue = item.fieldValue.ToObject>().Last();
break;
case "notLike": // 不包含
conditionalType = ConditionalType.NoLike;
+ item.fieldValue = item.fieldValue.ToObject>().Last();
break;
}
queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.RELATIONFORM:
switch (item.symbol)
{
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
+ case "notLike": // 不包含
+ conditionalType = ConditionalType.IsNullOrEmpty;
+ queryList.Add(ControlAdvancedQueryAssembly(WhereType.Or, item.jnpfKey, field, null, conditionalType));
break;
case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
+ conditionalType = ConditionalType.IsNullOrEmpty;
+ queryList.Add(ControlAdvancedQueryAssembly(WhereType.Or, item.jnpfKey, field, null, conditionalType));
break;
}
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.POPUPSELECT:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.CALCULATE:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.CREATEUSER:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.CREATETIME:
- if (item.fieldValue.IsNotEmptyOrNull()) item.fieldValue = string.Format("{0:yyyy-MM-dd HH:mm:ss}", item.fieldValue?.ToString().TimeStampToDateTime());
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.MODIFYUSER:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.MODIFYTIME:
- if (item.fieldValue.IsNotEmptyOrNull()) item.fieldValue = string.Format("{0:yyyy-MM-dd HH:mm:ss}", item.fieldValue?.ToString().TimeStampToDateTime());
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.CURRDEPT:
- switch (item.symbol)
- {
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
- break;
- case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
- break;
- }
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
break;
case JnpfKeyConst.CURRORGANIZE:
switch (item.symbol)
@@ -984,54 +382,39 @@ public class SuperQueryHelper
break;
case "==": // 等于
conditionalType = ConditionalType.Equal;
+ item.fieldValue = item.fieldValue.ToObject>().Last();
break;
case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
+ conditionalType = ConditionalType.LessThanOrEqual;
break;
case "<": // 小于
conditionalType = ConditionalType.LessThan;
break;
case "<>": // 不等于
conditionalType = ConditionalType.NoEqual;
+ item.fieldValue = item.fieldValue.ToObject>().Last();
break;
case "like": // 包含
- conditionalType = ConditionalType.Like;
+ conditionalType = ConditionalType.Equal;
+ item.fieldValue = item.fieldValue.ToObject>().Last();
break;
case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
+ conditionalType = ConditionalType.NoEqual;
+ item.fieldValue = item.fieldValue.ToObject>().Last();
break;
}
queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
- break;
- case JnpfKeyConst.CURRPOSITION:
switch (item.symbol)
{
- case ">=": // 大于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case ">": // 大于
- conditionalType = ConditionalType.GreaterThan;
- break;
- case "==": // 等于
- conditionalType = ConditionalType.Equal;
- break;
- case "<=": // 小于等于
- conditionalType = ConditionalType.GreaterThanOrEqual;
- break;
- case "<": // 小于
- conditionalType = ConditionalType.LessThan;
+ case "notLike": // 不包含
+ conditionalType = ConditionalType.IsNullOrEmpty;
+ queryList.Add(ControlAdvancedQueryAssembly(WhereType.Or, item.jnpfKey, field, null, conditionalType));
break;
case "<>": // 不等于
- conditionalType = ConditionalType.NoEqual;
- break;
- case "like": // 包含
- conditionalType = ConditionalType.Like;
- break;
- case "notLike": // 不包含
- conditionalType = ConditionalType.NoLike;
+ conditionalType = ConditionalType.IsNullOrEmpty;
+ queryList.Add(ControlAdvancedQueryAssembly(WhereType.Or, item.jnpfKey, field, null, conditionalType));
break;
}
- queryList.Add(ControlAdvancedQueryAssembly(whereType, item.jnpfKey, field, item.fieldValue.ParseToString(), conditionalType, true));
break;
}
}
@@ -1039,7 +422,7 @@ public class SuperQueryHelper
return queryList;
}
- public static ConvertSuperQuery ControlAdvancedQueryAssembly(WhereType whereType, string jnpfKey, string field, string fieldValue, ConditionalType conditionalType, bool mainWhere = false)
+ public static ConvertSuperQuery ControlAdvancedQueryAssembly(WhereType whereType, string jnpfKey, string field, string fieldValue, ConditionalType conditionalType, bool mainWhere = false, string symbol = "")
{
return new ConvertSuperQuery
{
@@ -1048,7 +431,8 @@ public class SuperQueryHelper
field = field,
fieldValue = fieldValue,
conditionalType = conditionalType,
- mainWhere = mainWhere
+ mainWhere = mainWhere,
+ symbol = symbol
};
}
@@ -1087,13 +471,13 @@ public class SuperQueryHelper
private static List> GetUserRelationByUserId(string fieldValue)
{
// 获取数据库连接选项
- ConnectionStringsOptions conn = App.GetConfig("ConnectionStrings", true);
+ ConnectionStringsOptions connectionStrings = App.GetConfig("ConnectionStrings", true);
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig
{
- ConnectionString = string.Format(conn.DefaultConnection, conn.Host, conn.Port, conn.DBName, conn.UserName, conn.Password),
- DbType = (DbType)Enum.Parse(typeof(DbType), conn.DBType),
+ ConnectionString = connectionStrings.ConnectString, // string.Format(connectionStrings.DefaultConnection, connectionStrings.DBName),
+ DbType = (DbType)Enum.Parse(typeof(DbType), connectionStrings.DBType),
IsAutoCloseConnection = true,
- ConfigId = conn.ConfigId,
+ ConfigId = connectionStrings.ConfigId,
InitKeyType = InitKeyType.Attribute,
MoreSettings = new ConnMoreSettings()
{
diff --git a/common/Tnb.Common/Security/XmlHelper.cs b/common/Tnb.Common/Security/XmlHelper.cs
index bd6f45f6..accc0c1e 100644
--- a/common/Tnb.Common/Security/XmlHelper.cs
+++ b/common/Tnb.Common/Security/XmlHelper.cs
@@ -4,11 +4,11 @@ namespace JNPF.Common.Security;
public static class XmlHelper
{
- ///
- /// 反序列化
- ///
- /// 类型
- /// XML字符串
+ ///
+ /// 反序列化.
+ ///
+ /// 类型.
+ /// XML字符串.
///
public static object Deserialize(Type type, string xml)
{
@@ -19,13 +19,12 @@ public static class XmlHelper
}
}
- ///
- /// 反序列化
- ///
- ///
- ///
- ///
-
+ ///
+ /// 反序列化.
+ ///
+ /// 类型.
+ /// XML流.
+ ///
public static object Deserialize(Type type, Stream stream)
{
XmlSerializer xmldes = new XmlSerializer(type);
diff --git a/common/Tnb.SqlSugar/Extensions/TenantLinkExtensions.cs b/common/Tnb.SqlSugar/Extensions/TenantLinkExtensions.cs
index d9f39627..723aafd0 100644
--- a/common/Tnb.SqlSugar/Extensions/TenantLinkExtensions.cs
+++ b/common/Tnb.SqlSugar/Extensions/TenantLinkExtensions.cs
@@ -1,4 +1,5 @@
-using JNPF.DataEncryption;
+using JNPF;
+using JNPF.DataEncryption;
using JNPF.Extras.DatabaseAccessor.SqlSugar;
using JNPF.Extras.DatabaseAccessor.SqlSugar.Extensions;
using Microsoft.Extensions.Configuration;
@@ -11,8 +12,7 @@ namespace SqlSugar;
///
public class JNPFTenantExtensions
{
- //public static IConfiguration _config { get; set; }
- private static ConnectionStringsOptions _connOpt { get; }
+ public static IConfiguration _config { get; set; }
public static string skey = "Vl4WTqna9aZCgswjieIP";
@@ -21,8 +21,7 @@ public class JNPFTenantExtensions
///
static JNPFTenantExtensions()
{
- var config = new ConfigurationBuilder().AddJsonFile("Configurations/ConnectionStrings.json", true, true).Build();
- _connOpt = config.GetSection("ConnectionStrings").Get();
+ _config = new ConfigurationBuilder().Add(new JsonConfigurationSource { Path = "Configurations/ConnectionStrings.json", ReloadOnChange = true }).Build();
}
///
@@ -33,14 +32,15 @@ public class JNPFTenantExtensions
///
public static ConnectionConfigOptions GetLinkToOrdinary(string configId, string tableName)
{
+ ConnectionStringsOptions conn = App.GetConfig("ConnectionStrings", true);
+
List configList = new List();
- var connStr = string.Format(_connOpt.DefaultConnection, _connOpt.Host, _connOpt.Port, _connOpt.DBName, _connOpt.UserName, _connOpt.Password);
configList.Add(new DBConnectionConfig()
{
IsMaster = true,
ServiceName = tableName,
- dbType = ToDbType(_connOpt.DBType),
- connectionStr = DESCEncryption.Encrypt(connStr, skey)
+ dbType = (DbType)Enum.Parse(typeof(DbType), conn.DBType),
+ connectionStr = DESCEncryption.Encrypt(conn.ConnectString, skey)
});
return new ConnectionConfigOptions()
{
diff --git a/common/Tnb.SqlSugar/Models/ITenantFilter.cs b/common/Tnb.SqlSugar/Models/ITenantFilter.cs
new file mode 100644
index 00000000..8a92ca1d
--- /dev/null
+++ b/common/Tnb.SqlSugar/Models/ITenantFilter.cs
@@ -0,0 +1,15 @@
+using SqlSugar;
+
+namespace JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
+
+///
+/// 实体类基类.
+///
+public interface ITenantFilter
+{
+ ///
+ /// 租户id.
+ ///
+ [SugarColumn(ColumnName = "F_TenantId", ColumnDescription = "租户id")]
+ string TenantId { get; set; }
+}
\ No newline at end of file
diff --git a/common/Tnb.SqlSugar/Options/ConnectionStringsOptions.cs b/common/Tnb.SqlSugar/Options/ConnectionStringsOptions.cs
index 0cffa04a..90bba155 100644
--- a/common/Tnb.SqlSugar/Options/ConnectionStringsOptions.cs
+++ b/common/Tnb.SqlSugar/Options/ConnectionStringsOptions.cs
@@ -46,4 +46,6 @@ public sealed class ConnectionStringsOptions : IConfigurableOptions
/// 默认数据库连接字符串.
///
public string DefaultConnection { get; set; }
+
+ public string ConnectString { get { return string.Format(DefaultConnection, Host, Port, DBName, UserName, Password); } }
}
\ No newline at end of file
diff --git a/common/Tnb.SqlSugar/Options/TenantOptions.cs b/common/Tnb.SqlSugar/Options/TenantOptions.cs
index c22ef476..5ee2391f 100644
--- a/common/Tnb.SqlSugar/Options/TenantOptions.cs
+++ b/common/Tnb.SqlSugar/Options/TenantOptions.cs
@@ -12,6 +12,11 @@ public sealed class TenantOptions : IConfigurableOptions
///
public bool MultiTenancy { get; set; }
+ ///
+ /// 数据隔离类型 SCHEMA:库隔离 COLUMN:字段隔离.
+ ///
+ public string MultiTenancyType { get; set; }
+
///
/// 多租户数据接口.
///
diff --git a/common/Tnb.SqlSugar/Repositories/SqlSugarRepository.cs b/common/Tnb.SqlSugar/Repositories/SqlSugarRepository.cs
index 41df7e6e..e24fece9 100644
--- a/common/Tnb.SqlSugar/Repositories/SqlSugarRepository.cs
+++ b/common/Tnb.SqlSugar/Repositories/SqlSugarRepository.cs
@@ -1,11 +1,11 @@
using JNPF;
using JNPF.DataEncryption;
+using JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
using JNPF.FriendlyException;
using JNPF.JsonSerialization;
using JNPF.Logging;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
-using System.Text.RegularExpressions;
namespace SqlSugar;
@@ -16,95 +16,98 @@ namespace SqlSugar;
public partial class SqlSugarRepository : SimpleClient, ISqlSugarRepository
where TEntity : class, new()
{
- ///
- /// 构造函数
- ///
- ///
- public SqlSugarRepository(ISqlSugarClient context = null) : base(context)
- {
- // 获取数据库连接选项
- ConnectionStringsOptions connectionStrings = App.GetConfig("ConnectionStrings", true);
-
- // 获取多租户选项
- TenantOptions tenant = App.GetConfig("Tenant", true);
- var httpContext = App.HttpContext;
-
- base.Context = (SqlSugarScope)context;
-
- string tenantId = connectionStrings.ConfigId;
-
- if (httpContext?.GetEndpoint()?.Metadata?.GetMetadata() == null || !string.IsNullOrEmpty(httpContext?.Request.Query["token"]))
+ ///
+ /// 构造函数
+ ///
+ ///
+ public SqlSugarRepository(ISqlSugarClient context = null) : base(context)
{
- if (tenant.MultiTenancy && httpContext != null)
- {
- var connectionConfig = new ConnectionConfigOptions();
- if (httpContext.Request.Headers.ContainsKey("Authorization"))
+ // 获取数据库连接选项
+ ConnectionStringsOptions connectionStrings = App.GetConfig("ConnectionStrings", true);
+
+ // 获取多租户选项
+ TenantOptions tenant = App.GetConfig("Tenant", true);
+ var httpContext = App.HttpContext;
+
+ base.Context = (SqlSugarScope)context;
+
+ string tenantId = connectionStrings.ConfigId;
+ string tenantDbName = string.Empty;
+
+ if (httpContext?.GetEndpoint()?.Metadata?.GetMetadata() == null)
{
- connectionConfig = JSON.Deserialize(httpContext?.User.FindFirst("ConnectionConfig")?.Value);
- tenantId = connectionConfig.ConfigId;
+ if (tenant.MultiTenancy && httpContext != null)
+ {
+ var connectionConfig = JSON.Deserialize(httpContext?.User.FindFirst("ConnectionConfig")?.Value);
+ tenantId = connectionConfig.ConfigId;
+ tenantDbName = connectionConfig.ConfigList.FirstOrDefault().ServiceName;
+ if (!base.Context.AsTenant().IsAnyConnection(connectionConfig.ConfigId))
+ {
+ base.Context.AsTenant().AddConnection(JNPFTenantExtensions.GetConfig(connectionConfig));
+ }
+ base.Context = base.Context.AsTenant().GetConnectionScope(connectionConfig.ConfigId);
+
+ if (!base.Context.Ado.IsValidConnection())
+ {
+ throw Oops.Oh("数据库连接错误");
+ }
+ }
+ else
+ {
+ base.Context = base.Context.AsTenant().GetConnectionScope(tenantId);
+ }
}
- else if (!httpContext.Request.Headers.ContainsKey("Authorization"))
+ // 字段数据隔离
+ if (!"default".Equals(tenantId) && tenant.MultiTenancyType.Equals("COLUMN"))
{
- var token = Regex.Match(httpContext.Request.QueryString.Value, @"[?&]token=Bearer%20([\w\.-]+)($|&)").Groups[1].Value;
- var claims = JWTEncryption.ReadJwtToken(token.Replace("Bearer ", "").Replace("bearer ", ""))?.Claims;
- connectionConfig = JSON.Deserialize(claims.FirstOrDefault(e => e.Type == "ConnectionConfig").Value);
- tenantId = connectionConfig.ConfigId;
+ base.Context.QueryFilter.AddTableFilter(it => it.TenantId == tenantDbName);
+ base.Context.Aop.DataExecuting = (oldValue, entityInfo) =>
+ {
+ if (entityInfo.PropertyName == "TenantId" && entityInfo.OperationType == DataFilterType.InsertByObject)
+ {
+ entityInfo.SetValue(tenantDbName);
+ }
+ };
}
- if (!base.Context.AsTenant().IsAnyConnection(connectionConfig.ConfigId))
+ // 设置超时时间
+ base.Context.Ado.CommandTimeOut = 30;
+ base.Context.Aop.OnLogExecuted = (sql, pars) =>
{
- base.Context.AsTenant().AddConnection(JNPFTenantExtensions.GetConfig(connectionConfig));
- }
- base.Context = base.Context.AsTenant().GetConnectionScope(connectionConfig.ConfigId);
-
- if (!base.Context.Ado.IsValidConnection())
- {
- throw Oops.Oh("数据库连接错误");
- }
- }
- else
- {
- base.Context = base.Context.AsTenant().GetConnectionScope(tenantId);
- }
- }
-
- // 设置超时时间
- base.Context.Ado.CommandTimeOut = 30;
- base.Context.Aop.OnLogExecuted = (sql, pars) =>
- {
- var oldColor = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Green;
- var finalSql = UtilMethods.GetSqlString(Context.CurrentConnectionConfig.DbType, sql, pars);
- Console.WriteLine($"【{DateTime.Now.ToString("HH:mm:ss.fff")}——SQL执行完成】{Context.Ado.SqlExecutionTime.TotalMilliseconds} ms");
- Console.WriteLine(finalSql);
- Console.ForegroundColor = oldColor;
- if (Context.Ado.SqlExecutionTime.TotalMilliseconds > 3000)
- {
- Log.Warning($"慢查询: {Context.Ado.SqlExecutionTime.TotalMilliseconds}ms, SQL: " + finalSql);
- }
- Console.WriteLine();
- //App.PrintToMiniProfiler("SqlSugar", "Info", sql + "\r\n" + base.Context.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
- };
- base.Context.Aop.OnError = (ex) =>
- {
- Log.Error("SQL执行错误: " + UtilMethods.GetSqlString(base.Context.CurrentConnectionConfig.DbType, ex.Sql, (SugarParameter[])ex.Parametres));
- //App.PrintToMiniProfiler("SqlSugar", "Error", $"{ex.Message}{Environment.NewLine}{ex.Sql}{pars}{Environment.NewLine}");
- };
-
- if (base.Context.CurrentConnectionConfig.DbType == DbType.Oracle)
- {
- base.Context.Aop.OnExecutingChangeSql = (sql, pars) =>
- {
- if (pars != null)
- {
- foreach (var item in pars)
- {
- //如果是DbTppe=string设置成OracleDbType.Nvarchar2
- item.IsNvarchar2 = true;
- }
+ var oldColor = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Green;
+ var finalSql = UtilMethods.GetSqlString(Context.CurrentConnectionConfig.DbType, sql, pars);
+ Console.WriteLine($"【{DateTime.Now.ToString("HH:mm:ss.fff")}——SQL执行完成】{Context.Ado.SqlExecutionTime.TotalMilliseconds} ms");
+ Console.WriteLine(finalSql);
+ Console.ForegroundColor = oldColor;
+ if (Context.Ado.SqlExecutionTime.TotalMilliseconds > 3000)
+ {
+ Log.Warning($"慢查询: {Context.Ado.SqlExecutionTime.TotalMilliseconds}ms, SQL: " + finalSql);
+ }
+ Console.WriteLine();
+ //App.PrintToMiniProfiler("SqlSugar", "Info", sql + "\r\n" + base.Context.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
};
- return new KeyValuePair(sql, pars);
- };
+ base.Context.Aop.OnError = (ex) =>
+ {
+ Log.Error("SQL执行错误: " + UtilMethods.GetSqlString(base.Context.CurrentConnectionConfig.DbType, ex.Sql, (SugarParameter[])ex.Parametres));
+ //App.PrintToMiniProfiler("SqlSugar", "Error", $"{ex.Message}{Environment.NewLine}{ex.Sql}{pars}{Environment.NewLine}");
+ };
+
+
+ if (base.Context.CurrentConnectionConfig.DbType == DbType.Oracle)
+ {
+ base.Context.Aop.OnExecutingChangeSql = (sql, pars) =>
+ {
+ if (pars != null)
+ {
+ foreach (var item in pars)
+ {
+ //如果是DbTppe=string设置成OracleDbType.Nvarchar2
+ item.IsNvarchar2 = true;
+ }
+ };
+ return new KeyValuePair(sql, pars);
+ };
+ }
}
- }
}
\ No newline at end of file
diff --git a/common/Tnb.SqlSugar/Tnb.SqlSugar.csproj b/common/Tnb.SqlSugar/Tnb.SqlSugar.csproj
index 197c66e6..65402833 100644
--- a/common/Tnb.SqlSugar/Tnb.SqlSugar.csproj
+++ b/common/Tnb.SqlSugar/Tnb.SqlSugar.csproj
@@ -18,8 +18,8 @@
-
-
+
+
diff --git a/common/Tnb.WebSockets/Models/WebSocketClient.cs b/common/Tnb.WebSockets/Models/WebSocketClient.cs
index 7780d63d..f41ee5c7 100644
--- a/common/Tnb.WebSockets/Models/WebSocketClient.cs
+++ b/common/Tnb.WebSockets/Models/WebSocketClient.cs
@@ -64,6 +64,11 @@ public class WebSocketClient
///
public LoginMethod SingleLogin { get; set; }
+ ///
+ /// 单点登录标识.
+ ///
+ public string onlineTicket { get; set; }
+
///
/// token.
///
diff --git a/extend/Tnb.Extend.Entitys/Dto/Document/DocumentListOutput.cs b/extend/Tnb.Extend.Entitys/Dto/Document/DocumentListOutput.cs
index 42a024f6..6ab9381b 100644
--- a/extend/Tnb.Extend.Entitys/Dto/Document/DocumentListOutput.cs
+++ b/extend/Tnb.Extend.Entitys/Dto/Document/DocumentListOutput.cs
@@ -47,4 +47,19 @@ public class DocumentListOutput
/// 父级Id.
///
public string? parentId { get; set; }
+
+ ///
+ /// 文档下载地址.
+ ///
+ public string? uploaderUrl { get; set; }
+
+ ///
+ /// 文件路径.
+ ///
+ public string? filePath { get; set; }
+
+ ///
+ /// 是否支持预览.
+ ///
+ public string? isPreview { get; set; }
}
diff --git a/extend/Tnb.Extend.Entitys/Dto/Product/ProductCrInput.cs b/extend/Tnb.Extend.Entitys/Dto/Product/ProductCrInput.cs
index 9bcb2455..01038191 100644
--- a/extend/Tnb.Extend.Entitys/Dto/Product/ProductCrInput.cs
+++ b/extend/Tnb.Extend.Entitys/Dto/Product/ProductCrInput.cs
@@ -87,17 +87,17 @@ public class ProductCrInput
///
/// 让利金额.
///
- public decimal partPrice { get; set; }
+ public decimal? partPrice { get; set; }
///
/// 优惠金额.
///
- public decimal reducedPrice { get; set; }
+ public decimal? reducedPrice { get; set; }
///
/// 折后金额.
///
- public decimal discountPrice { get; set; }
+ public decimal? discountPrice { get; set; }
///
/// 备注.
diff --git a/extend/Tnb.Extend.Entitys/Dto/Product/ProductInfoOutput.cs b/extend/Tnb.Extend.Entitys/Dto/Product/ProductInfoOutput.cs
index 8cf39190..1976c821 100644
--- a/extend/Tnb.Extend.Entitys/Dto/Product/ProductInfoOutput.cs
+++ b/extend/Tnb.Extend.Entitys/Dto/Product/ProductInfoOutput.cs
@@ -92,17 +92,17 @@ public class ProductInfoOutput
///
/// 让利金额.
///
- public decimal partPrice { get; set; }
+ public decimal? partPrice { get; set; }
///
/// 优惠金额.
///
- public decimal reducedPrice { get; set; }
+ public decimal? reducedPrice { get; set; }
///
/// 折后金额.
///
- public decimal discountPrice { get; set; }
+ public decimal? discountPrice { get; set; }
///
/// 备注.
diff --git a/extend/Tnb.Extend.Entitys/Dto/Product/ProductListOutput.cs b/extend/Tnb.Extend.Entitys/Dto/Product/ProductListOutput.cs
index dc56c981..0dc6fa52 100644
--- a/extend/Tnb.Extend.Entitys/Dto/Product/ProductListOutput.cs
+++ b/extend/Tnb.Extend.Entitys/Dto/Product/ProductListOutput.cs
@@ -67,4 +67,9 @@ public class ProductListOutput
/// 联系人.
///
public string contactName { get; set; }
+
+ ///
+ /// 子表数据.
+ ///
+ public List productEntryList { get; set; }
}
\ No newline at end of file
diff --git a/extend/Tnb.Extend.Entitys/Dto/Customer/CustomerListOutput.cs b/extend/Tnb.Extend.Entitys/Dto/ProductCustomer/ProductCustomerListOutput.cs
similarity index 95%
rename from extend/Tnb.Extend.Entitys/Dto/Customer/CustomerListOutput.cs
rename to extend/Tnb.Extend.Entitys/Dto/ProductCustomer/ProductCustomerListOutput.cs
index cfff8590..21aa8fdc 100644
--- a/extend/Tnb.Extend.Entitys/Dto/Customer/CustomerListOutput.cs
+++ b/extend/Tnb.Extend.Entitys/Dto/ProductCustomer/ProductCustomerListOutput.cs
@@ -7,7 +7,7 @@ namespace JNPF.Extend.Entitys.Dto.Customer;
/// 客户信息.
///
[SuppressSniffer]
-public class CustomerListOutput
+public class ProductCustomerListOutput
{
///
/// 主键.
diff --git a/extend/Tnb.Extend.Entitys/Entity/BigDataEntity.cs b/extend/Tnb.Extend.Entitys/Entity/BigDataEntity.cs
index 5be87cd3..7b29de88 100644
--- a/extend/Tnb.Extend.Entitys/Entity/BigDataEntity.cs
+++ b/extend/Tnb.Extend.Entitys/Entity/BigDataEntity.cs
@@ -1,4 +1,5 @@
using JNPF.Common.Contracts;
+using JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
using SqlSugar;
namespace JNPF.Extend.Entitys;
diff --git a/extend/Tnb.Extend.Entitys/Entity/DocumentEntity.cs b/extend/Tnb.Extend.Entitys/Entity/DocumentEntity.cs
index e3fb9113..f187c65d 100644
--- a/extend/Tnb.Extend.Entitys/Entity/DocumentEntity.cs
+++ b/extend/Tnb.Extend.Entitys/Entity/DocumentEntity.cs
@@ -78,4 +78,10 @@ public class DocumentEntity : CLDEntityBase
///
[SugarColumn(ColumnName = "F_SORTCODE")]
public long? SortCode { get; set; }
+
+ ///
+ /// 下载地址.
+ ///
+ [SugarColumn(ColumnName = "F_UPLOADERURL")]
+ public string? UploaderUrl { get; set; }
}
diff --git a/extend/Tnb.Extend.Entitys/Entity/CustomerEntity.cs b/extend/Tnb.Extend.Entitys/Entity/ProductCustomerEntity.cs
similarity index 96%
rename from extend/Tnb.Extend.Entitys/Entity/CustomerEntity.cs
rename to extend/Tnb.Extend.Entitys/Entity/ProductCustomerEntity.cs
index c7bee238..76bc96bd 100644
--- a/extend/Tnb.Extend.Entitys/Entity/CustomerEntity.cs
+++ b/extend/Tnb.Extend.Entitys/Entity/ProductCustomerEntity.cs
@@ -7,7 +7,7 @@ namespace JNPF.Extend.Entitys.Entity;
/// 客户信息.
///
[SugarTable("ext_customer", TableDescription = "客户信息")]
-public class CustomerEntity : CLEntityBase
+public class ProductCustomerEntity : CLEntityBase
{
///
/// 编码.
diff --git a/extend/Tnb.Extend.Entitys/Entity/ProductEntity.cs b/extend/Tnb.Extend.Entitys/Entity/ProductEntity.cs
index a0c4ccfa..00144cd5 100644
--- a/extend/Tnb.Extend.Entitys/Entity/ProductEntity.cs
+++ b/extend/Tnb.Extend.Entitys/Entity/ProductEntity.cs
@@ -159,19 +159,19 @@ public class ProductEntity : EntityBase
/// 让利金额.
///
[SugarColumn(ColumnName = "F_PartPrice")]
- public decimal PartPrice { get; set; }
+ public decimal? PartPrice { get; set; }
///
/// 优惠金额.
///
[SugarColumn(ColumnName = "F_ReducedPrice")]
- public decimal ReducedPrice { get; set; }
+ public decimal? ReducedPrice { get; set; }
///
/// 折后金额.
///
[SugarColumn(ColumnName = "F_DiscountPrice")]
- public decimal DiscountPrice { get; set; }
+ public decimal? DiscountPrice { get; set; }
///
/// 备注.
diff --git a/extend/Tnb.Extend.Entitys/Entity/ProductgoodsEntity.cs b/extend/Tnb.Extend.Entitys/Entity/ProductgoodsEntity.cs
index 9765623a..3e587ce7 100644
--- a/extend/Tnb.Extend.Entitys/Entity/ProductgoodsEntity.cs
+++ b/extend/Tnb.Extend.Entitys/Entity/ProductgoodsEntity.cs
@@ -9,7 +9,7 @@ namespace JNPF.Extend.Entitys;
///
[SugarTable("ext_productgoods")]
[Tenant(ClaimConst.TENANTID)]
-public class ProductgoodsEntity
+public class ProductGoodsEntity
{
///
/// 主键.
diff --git a/extend/Tnb.Extend/DocumentService.cs b/extend/Tnb.Extend/DocumentService.cs
index 185a6e43..b04bedd2 100644
--- a/extend/Tnb.Extend/DocumentService.cs
+++ b/extend/Tnb.Extend/DocumentService.cs
@@ -84,6 +84,12 @@ public class DocumentService : IDynamicApiController, ITransient
.WhereIF(input.keyword.IsNotEmptyOrNull(), t => t.FullName.Contains(input.keyword))
.OrderBy(x => x.SortCode).OrderBy(x => x.CreatorTime, OrderByType.Desc)
.OrderByIF(!string.IsNullOrEmpty(input.keyword), t => t.LastModifyTime, OrderByType.Desc).ToListAsync()).Adapt>();
+ string[]? typeList = new string[] { "doc", "docx", "xls", "xlsx", "ppt", "pptx", "pdf", "jpg", "jpeg", "gif", "png", "bmp" };
+ foreach (var item in data)
+ {
+ string? type = item.fullName.Split('.').LastOrDefault();
+ item.isPreview = typeList.Contains(type) ? "1" : null;
+ }
return new { list = data };
}
@@ -248,6 +254,7 @@ public class DocumentService : IDynamicApiController, ITransient
entity.FilePath = Path.Combine(_filePath, input.file.FileName);
entity.FileSize = input.file.Length.ToString();
entity.DeleteMark = 0;
+ entity.UploaderUrl = string.Format("/api/file/Image/document/{0}", entity.FilePath);
var isOk = await _repository.AsSugarClient().Insertable(entity).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
if (isOk < 1)
throw Oops.Oh(ErrorCode.D8001);
@@ -261,11 +268,12 @@ public class DocumentService : IDynamicApiController, ITransient
[HttpPost("merge")]
public async Task merge([FromForm] ChunkModel input)
{
- if (await _repository.IsAnyAsync(x => x.FullName == input.fileName && x.Type == 1 && x.DeleteMark != 1))
+ if (await _repository.IsAnyAsync(x =>x.CreatorUserId==_userManager.UserId && x.FullName == input.fileName && x.Type == 1 && x.DeleteMark != 1))
{
- string directoryPath = Path.Combine(App.GetConfig("JNPF_App", true).SystemPath, "TemporaryFile", input.identifier);
- FileHelper.DeleteDirectory(directoryPath);
- throw Oops.Oh(ErrorCode.D8002);
+ //string directoryPath = Path.Combine(App.GetConfig("JNPF_App", true).SystemPath, "TemporaryFile", input.identifier);
+ //FileHelper.DeleteDirectory(directoryPath);
+ //throw Oops.Oh(ErrorCode.D8002);
+ input.fileName = string.Format("{0}-{1}", DateTime.Now.ParseToUnixTime(), input.fileName);
}
input.isUpdateName = false;
input.type = "document";
@@ -276,10 +284,11 @@ public class DocumentService : IDynamicApiController, ITransient
entity.Type = 1;
entity.FullName = input.fileName;
entity.ParentId = input.parentId;
- entity.FileExtension = Path.GetExtension(input.fileName).Replace(".", string.Empty);
+ entity.FileExtension = input.extension;
entity.FilePath = output.name;
entity.FileSize = input.fileSize;
entity.DeleteMark = 0;
+ entity.UploaderUrl = string.Format("/api/file/Image/document/{0}", entity.FilePath);
var isOk = await _repository.AsSugarClient().Insertable(entity).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
if (isOk < 1)
throw Oops.Oh(ErrorCode.D8001);
@@ -299,8 +308,7 @@ public class DocumentService : IDynamicApiController, ITransient
throw Oops.Oh(ErrorCode.D8000);
var fileName = _userManager.UserId + "|" + entity.FilePath + "|document";
_cacheManager.Set(entity.FilePath, string.Empty);
- return new
- {
+ return new {
name = entity.FullName,
url = "/api/File/Download?encryption=" + DESCEncryption.Encrypt(fileName, "JNPF")
};
diff --git a/extend/Tnb.Extend/EmailService.cs b/extend/Tnb.Extend/EmailService.cs
index 270505a2..bc67f23d 100644
--- a/extend/Tnb.Extend/EmailService.cs
+++ b/extend/Tnb.Extend/EmailService.cs
@@ -233,7 +233,7 @@ public class EmailService : IDynamicApiController, ITransient
var mailAccount = mailConfig.Adapt();
if (MailUtil.CheckConnected(mailAccount))
{
- new List();
+ new List();
var startTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd") + " 00:00");
var endTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd") + " 23:59");
var receiveCount = await _repository.AsSugarClient().Queryable().CountAsync(x => x.MAccount == mailConfig.Account && SqlFunc.Between(x.CreatorTime, startTime, endTime));
@@ -331,7 +331,7 @@ public class EmailService : IDynamicApiController, ITransient
var mailFilePath = FileVariable.EmailFilePath;
foreach (MailFileParameterInfo mailFile in attachmentList)
{
- FileHelper.MoveFile(Path.Combine(temporaryFile , mailFile.fileId), Path.Combine(mailFilePath , mailFile.fileId));
+ FileHelper.MoveFile(Path.Combine(temporaryFile, mailFile.fileId), Path.Combine(mailFilePath, mailFile.fileId));
mailFile.fileName = mailFile.name;
}
//发送邮件
@@ -342,7 +342,7 @@ public class EmailService : IDynamicApiController, ITransient
mailModel.Subject = entity.Subject;
mailModel.BodyText = HttpUtility.HtmlDecode(entity.BodyText);
mailModel.Attachment = attachmentList;
- MailUtil.Send(new MailParameterInfo { AccountName = mailConfig.SenderName, Account = mailConfig.Account, Password = mailConfig.Password, SMTPHost = mailConfig.SMTPHost, SMTPPort = mailConfig.SMTPPort.ParseToInt() }, mailModel);
+ MailUtil.Send(new MailParameterInfo { AccountName = mailConfig.SenderName, Account = mailConfig.Account, Password = mailConfig.Password, SMTPHost = mailConfig.SMTPHost, SMTPPort = mailConfig.SMTPPort.ParseToInt(), Ssl = mailConfig.Ssl == 1 }, mailModel);
if (isOk < 1)
throw Oops.Oh(ErrorCode.COM1008);
}
@@ -396,10 +396,10 @@ public class EmailService : IDynamicApiController, ITransient
[HttpPost("Download")]
public async Task Download(AnnexModel fileModel)
{
- var filePath = Path.Combine(FileVariable.EmailFilePath , fileModel.FileId);
+ var filePath = Path.Combine(FileVariable.EmailFilePath, fileModel.FileId);
if (await _fileManager.ExistsFile(filePath))
{
- _fileManager.DownloadFileByType(filePath, fileModel.FileName);
+ _fileManager.DownloadFileByType(filePath, fileModel.FileName);
}
}
diff --git a/extend/Tnb.Extend/EmployeeService.cs b/extend/Tnb.Extend/EmployeeService.cs
index a5f64f22..fa4ac24e 100644
--- a/extend/Tnb.Extend/EmployeeService.cs
+++ b/extend/Tnb.Extend/EmployeeService.cs
@@ -5,6 +5,7 @@ using JNPF.Common.Enums;
using JNPF.Common.Extension;
using JNPF.Common.Filter;
using JNPF.Common.Helper;
+using JNPF.Common.Manager;
using JNPF.Common.Models.NPOI;
using JNPF.Common.Security;
using JNPF.DataEncryption;
@@ -34,12 +35,14 @@ public class EmployeeService : IDynamicApiController, ITransient
private readonly ISqlSugarRepository _repository;
private readonly IFileManager _fileManager;
private readonly IUserManager _userManager;
+ private readonly ICacheManager _cacheManager;
- public EmployeeService(ISqlSugarRepository repository, IFileManager fileManager, IUserManager userManager)
+ public EmployeeService(ISqlSugarRepository repository, IFileManager fileManager, IUserManager userManager,ICacheManager cacheManager)
{
_repository = repository;
_fileManager = fileManager;
_userManager = userManager;
+ _cacheManager = cacheManager;
}
#region GET
@@ -114,6 +117,7 @@ public class EmployeeService : IDynamicApiController, ITransient
//得到数据
var sr = await _fileManager.GetFileStream(savePath);
var excelData = ExcelImportHelper.ToDataTable(savePath, sr);
+ excelData.Rows.RemoveAt(0);
foreach (var item in excelData.Columns)
{
excelData.Columns[item.ToString()].ColumnName = GetFiledEncode(item.ToString());
@@ -200,6 +204,7 @@ public class EmployeeService : IDynamicApiController, ITransient
var addPath = Path.Combine(FileVariable.TemporaryFilePath, excelconfig.FileName);
var stream = ExcelExportHelper.ExportMemoryStream(dataList, excelconfig);
await _fileManager.UploadFileByType(stream, FileVariable.TemporaryFilePath, excelconfig.FileName);
+ _cacheManager.Set(excelconfig.FileName, string.Empty);
return new { name = excelconfig.FileName, url = "/api/file/Download?encryption=" + DESCEncryption.Encrypt(_userManager.UserId + "|" + excelconfig.FileName + "|" + addPath, "JNPF") };
}
@@ -214,6 +219,7 @@ public class EmployeeService : IDynamicApiController, ITransient
var _fileName = DateTime.Now.ToString("yyyyMMdd") + "_" + SnowflakeIdHelper.NextId() + Path.GetExtension(file.FileName);
var stream = file.OpenReadStream();
await _fileManager.UploadFileByType(stream, _filePath, _fileName);
+ _cacheManager.Set(_fileName, string.Empty);
return new { name = _fileName, url = string.Format("/api/File/Image/{0}/{1}", string.Empty, _fileName) };
}
@@ -267,6 +273,7 @@ public class EmployeeService : IDynamicApiController, ITransient
{
var stream = await _fileManager.GetFileStream(filePath);
await _fileManager.UploadFileByType(stream, FileVariable.TemporaryFilePath, "职员信息.xlsx");
+ _cacheManager.Set("职员信息.xlsx", string.Empty);
}
return new { name = "职员信息.xlsx", url = "/api/file/Download?encryption=" + DESCEncryption.Encrypt(_userManager.UserId + "|职员信息.xlsx", "JNPF") };
}
diff --git a/extend/Tnb.Extend/OrderService.cs b/extend/Tnb.Extend/OrderService.cs
index 25117549..a99b328c 100644
--- a/extend/Tnb.Extend/OrderService.cs
+++ b/extend/Tnb.Extend/OrderService.cs
@@ -44,14 +44,12 @@ public class OrderService : IDynamicApiController, ITransient
ISqlSugarRepository repository,
IUserManager userManager,
IUsersService usersService,
- ICacheManager cacheManager,
- IFileManager fileManager)
+ ICacheManager cacheManager)
{
_repository = repository;
_userManager = userManager;
_usersService = usersService;
_cacheManager = cacheManager;
- _fileManager = fileManager;
}
#region GET
@@ -141,6 +139,7 @@ public class OrderService : IDynamicApiController, ITransient
[HttpGet("{id}")]
public async Task GetInfo(string id)
{
+ if ("0".Equals(id)) return null;
var data = (await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null)).Adapt();
if (data.IsNullOrEmpty()) return null;
data.collectionPlanList = (await _repository.AsSugarClient().Queryable().Where(x => x.OrderId == id).ToListAsync()).Adapt>();
diff --git a/extend/Tnb.Extend/ProductClassifyService.cs b/extend/Tnb.Extend/ProductClassifyService.cs
index ce8eba2b..6b77a037 100644
--- a/extend/Tnb.Extend/ProductClassifyService.cs
+++ b/extend/Tnb.Extend/ProductClassifyService.cs
@@ -30,10 +30,10 @@ public class ProductClassifyService : IDynamicApiController, ITransient
private readonly IUserManager _userManager;
public ProductClassifyService(
- ISqlSugarRepository extProductRepository,
+ ISqlSugarRepository repository,
IUserManager userManager)
{
- _repository = extProductRepository;
+ _repository = repository;
_userManager = userManager;
}
diff --git a/extend/Tnb.Extend/ProductCustomerService.cs b/extend/Tnb.Extend/ProductCustomerService.cs
new file mode 100644
index 00000000..4198f04c
--- /dev/null
+++ b/extend/Tnb.Extend/ProductCustomerService.cs
@@ -0,0 +1,65 @@
+using JNPF.Common.Core.Manager;
+using JNPF.Common.Filter;
+using Microsoft.AspNetCore.Mvc;
+using SqlSugar;
+using JNPF.DynamicApiController;
+using JNPF.DependencyInjection;
+using JNPF.Common.Extension;
+using JNPF.Extend.Entitys.Entity;
+using JNPF.Extend.Entitys.Dto.Customer;
+
+namespace JNPF.Extend;
+
+///
+/// 客户信息.
+///
+[ApiDescriptionSettings(Tag = "Extend", Name = "Customer", Order = 600)]
+[Route("api/extend/saleOrder/[controller]")]
+public class ProductCustomerService : IDynamicApiController, ITransient
+{
+ ///
+ /// 服务基础仓储.
+ ///
+ private readonly ISqlSugarRepository _repository;
+
+ ///
+ /// 用户管理.
+ ///
+ private readonly IUserManager _userManager;
+
+ public ProductCustomerService(
+ ISqlSugarRepository repository,
+ IUserManager userManager)
+ {
+ _repository = repository;
+ _userManager = userManager;
+ }
+
+ #region GET
+
+ ///
+ /// 客户列表.
+ ///
+ ///
+ [HttpGet("")]
+ public async Task GetList([FromQuery] PageInputBase input)
+ {
+ var data = await _repository.AsQueryable()
+ .Where(it => it.Deletemark == null)
+ .WhereIF(input.keyword.IsNotEmptyOrNull(), x => x.Name.Contains(input.keyword))
+ .Select(x => new ProductCustomerListOutput
+ {
+ id = x.Id,
+ code = x.Code,
+ name = x.Name,
+ customerName = x.Customername,
+ address = x.Address,
+ contactTel = x.ContactTel
+ })
+ .ToListAsync();
+
+ return new { list = data };
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/extend/Tnb.Extend/ProductGoodsService.cs b/extend/Tnb.Extend/ProductGoodsService.cs
new file mode 100644
index 00000000..73de5aaf
--- /dev/null
+++ b/extend/Tnb.Extend/ProductGoodsService.cs
@@ -0,0 +1,87 @@
+using JNPF.Common.Core.Manager;
+using JNPF.Common.Extension;
+using JNPF.Common.Filter;
+using JNPF.DependencyInjection;
+using JNPF.DynamicApiController;
+using JNPF.Extend.Entitys;
+using JNPF.Extend.Entitys.Dto.ProductGoods;
+using Microsoft.AspNetCore.Mvc;
+using SqlSugar;
+
+namespace JNPF.Extend;
+
+///
+/// 选择产品.
+///
+[ApiDescriptionSettings(Tag = "Extend", Name = "Goods", Order = 600)]
+[Route("api/extend/saleOrder/[controller]")]
+public class ProductGoodsService : IDynamicApiController, ITransient
+{
+ ///
+ /// 服务基础仓储.
+ ///
+ private readonly ISqlSugarRepository _repository;
+
+ ///
+ /// 用户管理.
+ ///
+ private readonly IUserManager _userManager;
+
+ public ProductGoodsService(
+ ISqlSugarRepository repository,
+ IUserManager userManager)
+ {
+ _repository = repository;
+ _userManager = userManager;
+ }
+
+ #region GET
+
+ ///
+ /// 产品列表.
+ ///
+ ///
+ [HttpGet("")]
+ public async Task GetList([FromQuery] ProductGoodsListQueryInput input)
+ {
+ var data = await _repository.AsQueryable()
+ .Where(it => it.DeleteMark == null)
+ .WhereIF(!string.IsNullOrEmpty(input.classifyId), it => it.ClassifyId.Equals(input.classifyId))
+ .WhereIF(!string.IsNullOrEmpty(input.code), it => it.Code.Contains(input.code))
+ .WhereIF(!string.IsNullOrEmpty(input.fullName), it => it.FullName.Contains(input.fullName))
+ .Select(it => new ProductGoodsListOutput
+ {
+ id = it.Id,
+ code = it.Code,
+ fullName = it.FullName,
+ qty = it.Qty,
+ }).MergeTable().OrderByIF(string.IsNullOrEmpty(input.sidx), it => it.id).OrderByIF(!string.IsNullOrEmpty(input.sidx), input.sidx + " " + input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
+ return PageResult.SqlSugarPageResult(data);
+ }
+
+ ///
+ /// 商品编码.
+ ///
+ ///
+ [HttpGet("Selector")]
+ public async Task GetSelectorList([FromQuery] PageInputBase input)
+ {
+ var data = await _repository.AsQueryable()
+ .Where(it => it.DeleteMark == null)
+ .WhereIF(input.keyword.IsNotEmptyOrNull(), x => x.Code.Contains(input.keyword))
+ .Select(it => new ProductGoodsListOutput
+ {
+ id = it.Id,
+ classifyId = it.ClassifyId,
+ code = it.Code,
+ fullName = it.FullName,
+ qty = it.Qty,
+ type = it.Type,
+ amount = it.Amount,
+ money = it.Money,
+ }).ToListAsync();
+ return new { list = data };
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/extend/Tnb.Extend/ProductService.cs b/extend/Tnb.Extend/ProductService.cs
index 505f07e9..41324786 100644
--- a/extend/Tnb.Extend/ProductService.cs
+++ b/extend/Tnb.Extend/ProductService.cs
@@ -43,11 +43,11 @@ public class ProductService : IDynamicApiController, ITransient
/// 初始化一个类型的新实例.
///
public ProductService(
- ISqlSugarRepository extProductRepository,
+ ISqlSugarRepository repository,
IBillRullService billRullService,
IUserManager userManager)
{
- _repository = extProductRepository;
+ _repository = repository;
_billRullService = billRullService;
_userManager = userManager;
}
@@ -74,7 +74,8 @@ public class ProductService : IDynamicApiController, ITransient
Price = it.Price,
Amount = it.Amount,
Description = it.Description
- }).ToList()).Where(a => a.Id.Equals(id) && a.DeleteMark == null)
+ }).ToList())
+ .Where(it => it.Id.Equals(id) && it.DeleteMark == null)
.ToListAsync(it => new ProductInfoOutput
{
id = it.Id,
@@ -100,6 +101,52 @@ public class ProductService : IDynamicApiController, ITransient
}))?.FirstOrDefault();
}
+ ///
+ /// 获取全订单示例.
+ ///
+ /// 请求参数.
+ ///
+ [HttpGet("Goods")]
+ public async Task GetAllProductEntryList([FromQuery] ProductListQueryInput input)
+ {
+ var data = await _repository.AsQueryable()
+ .Includes(x => x.productEntryList.Where(it => it.DeleteMark == null).Select(it => new ProductEntryEntity
+ {
+ ProductCode = it.ProductCode,
+ ProductName = it.ProductName,
+ ProductSpecification = it.ProductSpecification,
+ Qty = it.Qty,
+ Type = it.Type,
+ Money = it.Money,
+ Price = it.Price,
+ Amount = it.Amount,
+ Description = it.Description,
+ Activity = it.Activity
+ }).ToList())
+ .Where(it => it.DeleteMark == null)
+ .WhereIF(!string.IsNullOrEmpty(input.code), it => it.Code.Contains(input.code))
+ .WhereIF(!string.IsNullOrEmpty(input.customerName), it => it.CustomerName.Contains(input.customerName))
+ .OrderByIF(string.IsNullOrEmpty(input.sidx), it => it.Id)
+ .OrderByIF(!string.IsNullOrEmpty(input.sidx), input.sidx + " " + input.sort)
+ .ToPagedListAsync(input.currentPage, input.pageSize, it => new ProductListOutput
+ {
+ id = it.Id,
+ code = it.Code,
+ customerName = it.CustomerName,
+ business = it.Business,
+ address = it.Address,
+ contactTel = it.ContactTel,
+ salesmanName = it.SalesmanName,
+ auditState = it.AuditState,
+ goodsState = it.GoodsState,
+ closeState = it.CloseState,
+ closeDate = it.CloseDate,
+ contactName = it.ContactName,
+ productEntryList = it.productEntryList.Adapt>()
+ });
+ return PageResult.SqlSugarPageResult(data);
+ }
+
///
/// 获取订单示例列表.
///
@@ -119,6 +166,7 @@ public class ProductService : IDynamicApiController, ITransient
.WhereIF(!string.IsNullOrEmpty(input.contactTel), it => it.ContactTel.Contains(input.contactTel))
.WhereIF(!string.IsNullOrEmpty(input.auditState), it => it.AuditState.Equals(input.auditState))
.WhereIF(!string.IsNullOrEmpty(input.closeState), it => it.CloseState.Equals(input.closeState))
+ .OrderByIF(string.IsNullOrEmpty(input.sidx), it => it.Id).OrderByIF(!string.IsNullOrEmpty(input.sidx), input.sidx + " " + input.sort)
.Select(it => new ProductListOutput
{
id = it.Id,
@@ -133,7 +181,7 @@ public class ProductService : IDynamicApiController, ITransient
closeState = it.CloseState,
closeDate = it.CloseDate,
contactName = it.ContactName
- }).MergeTable().OrderByIF(string.IsNullOrEmpty(input.sidx), it => it.id).OrderByIF(!string.IsNullOrEmpty(input.sidx), input.sidx + " " + input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
+ }).ToPagedListAsync(input.currentPage, input.pageSize);
return PageResult.SqlSugarPageResult(data);
}
diff --git a/message/Tnb.Message.Entitys/Dto/Message/MessageListOutput.cs b/message/Tnb.Message.Entitys/Dto/Message/MessageListOutput.cs
index 8afa66bd..be8c57d9 100644
--- a/message/Tnb.Message.Entitys/Dto/Message/MessageListOutput.cs
+++ b/message/Tnb.Message.Entitys/Dto/Message/MessageListOutput.cs
@@ -37,4 +37,5 @@ public class MessageListOutput
/// 是否已读(0-未读,1-已读).
///
public int? isRead { get; set; }
+ public int? flowType { get; set; }
}
\ No newline at end of file
diff --git a/message/Tnb.Message.Entitys/Entity/MessageEntity.cs b/message/Tnb.Message.Entitys/Entity/MessageEntity.cs
index 1339a6c9..ab55cc10 100644
--- a/message/Tnb.Message.Entitys/Entity/MessageEntity.cs
+++ b/message/Tnb.Message.Entitys/Entity/MessageEntity.cs
@@ -65,4 +65,6 @@ public class MessageEntity : CLDEntityBase
///
[SugarColumn(ColumnName = "F_FILES")]
public string Files { get; set; }
+ [SugarColumn(ColumnName = "F_FLOWTYPE")]
+ public int? FlowType { get; set; }
}
\ No newline at end of file
diff --git a/message/Tnb.Message.Interfaces/IMessageService.cs b/message/Tnb.Message.Interfaces/IMessageService.cs
index abb788ee..d9b18ce4 100644
--- a/message/Tnb.Message.Interfaces/IMessageService.cs
+++ b/message/Tnb.Message.Interfaces/IMessageService.cs
@@ -15,5 +15,5 @@ public interface IMessageService
///
///
///
- Task SentMessage(List toUserIds, string title, string bodyText = null, Dictionary bodyDic = null);
+ Task SentMessage(List toUserIds, string title, string bodyText = null, Dictionary bodyDic = null, int type = 2, string flowType = "1");
}
\ No newline at end of file
diff --git a/message/Tnb.Message.Interfaces/ISendMessageService.cs b/message/Tnb.Message.Interfaces/ISendMessageService.cs
index 439531b6..ceccaaf7 100644
--- a/message/Tnb.Message.Interfaces/ISendMessageService.cs
+++ b/message/Tnb.Message.Interfaces/ISendMessageService.cs
@@ -6,5 +6,7 @@ public interface ISendMessageService
{
Task SendMessage(MessageSendModel messageSendModel, Dictionary bodyDic);
- Task SendMessageDefult(string enCode, List toUser, string taskName, Dictionary bodyDic);
+ Task SendMessageDefult(string enCode, List toUser, string creatorUser, string flowName, Dictionary bodyDic);
+ Task SendMessageDelegate(string delegateType, string ToUserId, string flowName);
+ Task SendMessageSystem(string enCode);
}
\ No newline at end of file
diff --git a/message/Tnb.Message/Service/MessageAccountService.cs b/message/Tnb.Message/Service/MessageAccountService.cs
index c799ff82..af1cd157 100644
--- a/message/Tnb.Message/Service/MessageAccountService.cs
+++ b/message/Tnb.Message/Service/MessageAccountService.cs
@@ -95,7 +95,7 @@ public class MessageAccountService : IDynamicApiController, ITransient
[HttpPost("")]
public async Task Create([FromBody] MessageAccountListOutput input)
{
- if (await _repository.IsAnyAsync(x => (x.EnCode == input.enCode) && x.DeleteMark == null))
+ if (await _repository.IsAnyAsync(x => (x.EnCode == input.enCode) && x.Type == input.type && x.DeleteMark == null))
throw Oops.Oh(ErrorCode.COM1004);
var entity = input.Adapt();
var isOk = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
@@ -112,7 +112,7 @@ public class MessageAccountService : IDynamicApiController, ITransient
[HttpPut("{id}")]
public async Task Update(string id, [FromBody] MessageAccountListOutput input)
{
- if (await _repository.IsAnyAsync(x => x.Id != id && (x.EnCode == input.enCode) && x.DeleteMark == null))
+ if (await _repository.IsAnyAsync(x => x.Id != id && (x.EnCode == input.enCode) && x.Type == input.type && x.DeleteMark == null))
throw Oops.Oh(ErrorCode.COM1004);
if ((await _repository.AsSugarClient().Queryable().AnyAsync(x => x.AccountConfigId == id && x.DeleteMark == null)) && input.enabledMark == 0)
throw Oops.Oh(ErrorCode.D7013);
@@ -153,6 +153,8 @@ public class MessageAccountService : IDynamicApiController, ITransient
entity.FullName = string.Format("{0}副本{1}", entity.FullName, random);
entity.EnCode = string.Format("{0}{1}", entity.EnCode, random);
entity.EnabledMark = 0;
+ entity.LastModifyTime = null;
+ entity.LastModifyUserId = null;
if (entity.Type == "7")
{
entity.AppKey = string.Format("{0}{1}", entity.AppKey, random);
diff --git a/message/Tnb.Message/Service/MessageService.cs b/message/Tnb.Message/Service/MessageService.cs
index a9df9431..3e634ac4 100644
--- a/message/Tnb.Message/Service/MessageService.cs
+++ b/message/Tnb.Message/Service/MessageService.cs
@@ -119,7 +119,8 @@ public class MessageService : IMessageService, IDynamicApiController, ITransient
releaseUser = SqlFunc.MergeString(c.RealName, "/", c.Account),
title = a.Title,
type = a.Type,
- isRead = b.IsRead
+ isRead = b.IsRead,
+ flowType=a.FlowType
}).ToPagedListAsync(input.currentPage, input.pageSize);
return PageResult.SqlSugarPageResult(list);
}
@@ -297,7 +298,7 @@ public class MessageService : IMessageService, IDynamicApiController, ITransient
{
try
{
- _repository.AsSugarClient().Insertable(receiveEntityList).ExecuteCommandAsync();
+ _repository.AsSugarClient().Insertable(receiveEntityList).ExecuteCommand();
return _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Create()).ExecuteCommand();
}
@@ -317,7 +318,7 @@ public class MessageService : IMessageService, IDynamicApiController, ITransient
{
try
{
- _repository.AsSugarClient().Insertable(receiveEntityList).ExecuteCommandAsync();
+ _repository.AsSugarClient().Insertable(receiveEntityList).ExecuteCommand();
return _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommand();
}
catch (Exception)
@@ -405,7 +406,7 @@ public class MessageService : IMessageService, IDynamicApiController, ITransient
/// 标题.
/// 内容.
[NonAction]
- public async Task SentMessage(List toUserIds, string title, string bodyText = null, Dictionary bodyDic = null)
+ public async Task SentMessage(List toUserIds, string title, string bodyText = null, Dictionary bodyDic = null, int type = 2, string flowType = "1")
{
try
{
@@ -413,9 +414,10 @@ public class MessageService : IMessageService, IDynamicApiController, ITransient
entity.Id = SnowflakeIdHelper.NextId();
entity.Title = title;
entity.BodyText = bodyText;
- entity.Type = 2;
+ entity.Type = type;
entity.LastModifyTime = DateTime.Now;
entity.LastModifyUserId = _userManager.UserId;
+ entity.FlowType = flowType.ParseToInt();
List receiveEntityList = toUserIds
.Select(x => new MessageReceiveEntity()
{
@@ -432,7 +434,7 @@ public class MessageService : IMessageService, IDynamicApiController, ITransient
{
var userId = item.Replace("-delegate", string.Empty);
// 消息推送 - 指定用户
- await _imHandler.SendMessageToUserAsync(string.Format("{0}-{1}", _userManager.TenantId, item), new { method = "messagePush", messageType = 2, userId = _userManager.UserId, toUserId = toUserIds, title = entity.Title, unreadNoticeCount = 1, id = entity.Id }.ToJsonString());
+ await _imHandler.SendMessageToUserAsync(string.Format("{0}-{1}", _userManager.TenantId, userId), new { method = "messagePush", messageType = 2, userId = _userManager.UserId, toUserId = toUserIds, title = entity.Title, unreadNoticeCount = 1, id = entity.Id }.ToJsonString());
}
}
}
diff --git a/message/Tnb.Message/Service/MessageTemplateService.cs b/message/Tnb.Message/Service/MessageTemplateService.cs
index 3a3201b1..14df414f 100644
--- a/message/Tnb.Message/Service/MessageTemplateService.cs
+++ b/message/Tnb.Message/Service/MessageTemplateService.cs
@@ -194,6 +194,8 @@ public class MessageTemplateService : IDynamicApiController, ITransient
entity.Id = SnowflakeIdHelper.NextId();
entity.EnabledMark = 0;
entity.TemplateType = "0";
+ entity.LastModifyTime = null;
+ entity.LastModifyUserId = null;
if (entity.FullName.Length >= 50 || entity.EnCode.Length >= 50)
throw Oops.Oh(ErrorCode.COM1009);
var templateParamList = await _repository.AsSugarClient().Queryable().Where(x => x.TemplateId == id && x.DeleteMark == null).ToListAsync();
diff --git a/message/Tnb.Message/Service/SendMessageService.cs b/message/Tnb.Message/Service/SendMessageService.cs
index d0c81d80..e934651a 100644
--- a/message/Tnb.Message/Service/SendMessageService.cs
+++ b/message/Tnb.Message/Service/SendMessageService.cs
@@ -106,7 +106,7 @@ public class SendMessageService : ISendMessageService, IDynamicApiController, IT
{
fullName = b.FullName,
type = a.MessageType,
- }).ToListAsync();
+ }).Distinct().ToListAsync();
}
return PageResult.SqlSugarPageResult(list);
}
@@ -115,10 +115,8 @@ public class SendMessageService : ISendMessageService, IDynamicApiController, IT
public async Task GetSendList([FromQuery] MessageTemplateQuery input)
{
var list = await _repository.AsSugarClient().Queryable()
- .Where(a => a.DeleteMark == null)
+ .Where(a => a.DeleteMark == null && a.EnabledMark == 1 && a.TemplateType == "0")
.WhereIF(input.messageSource.IsNotEmptyOrNull(), a => a.MessageSource == input.messageSource)
- .WhereIF(input.templateType.IsNotEmptyOrNull(), a => a.TemplateType == input.templateType)
- .WhereIF(input.enabledMark.IsNotEmptyOrNull(), a => a.EnabledMark == input.enabledMark)
.WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword))
.OrderBy(a => a.SortCode)
.OrderBy(a => a.CreatorTime, OrderByType.Desc)
@@ -251,6 +249,10 @@ public class SendMessageService : ISendMessageService, IDynamicApiController, IT
entity.FullName = string.Format("{0}副本{1}", entity.FullName, random);
entity.EnCode = string.Format("{0}{1}", entity.EnCode, random);
entity.Id = SnowflakeIdHelper.NextId();
+ entity.EnabledMark = 0;
+ entity.TemplateType = "0";
+ entity.LastModifyTime = null;
+ entity.LastModifyUserId = null;
if (entity.FullName.Length >= 50 || entity.EnCode.Length >= 50)
throw Oops.Oh(ErrorCode.COM1009);
var sendTemplateList = await _repository.AsSugarClient().Queryable().Where(x => x.SendConfigId == id && x.DeleteMark == null).ToListAsync();
@@ -460,11 +462,11 @@ public class SendMessageService : ISendMessageService, IDynamicApiController, IT
return errorList.Any() ? string.Join(",", errorList) : string.Empty;
}
- public async Task SendMessageDefult(string enCode,List toUser, string taskName, Dictionary bodyDic)
+ public async Task SendMessageDefult(string enCode, List toUser,string creatorUser, string flowName, Dictionary bodyDic)
{
var msgTemplateEntity= await _repository.AsSugarClient().Queryable().FirstAsync(x => x.EnCode == enCode && x.TemplateType=="1" && x.DeleteMark == null);
- msgTemplateEntity.Title= msgTemplateEntity.Title.Replace("@流程发起人@流程名称", taskName);
- msgTemplateEntity.Content = msgTemplateEntity.Content.Replace("@流程发起人@流程名称", taskName);
+ msgTemplateEntity.Title = msgTemplateEntity.Title.Replace("@流程发起人", creatorUser).Replace("@流程名称", flowName);
+ msgTemplateEntity.Content = msgTemplateEntity.Content.Replace("@流程发起人", creatorUser).Replace("@流程名称", flowName);
await _messageService.SentMessage(toUser, msgTemplateEntity.Title, msgTemplateEntity.Content, bodyDic);
#region 消息监控
foreach (var item in toUser)
@@ -482,6 +484,21 @@ public class SendMessageService : ISendMessageService, IDynamicApiController, IT
}
#endregion
}
+ public async Task SendMessageDelegate(string delegateType, string ToUserId, string flowName)
+ {
+ var title = string.Format("{0}已{1}您的{2}流程!", _userManager.User.RealName, delegateType, flowName);
+ var parameter = new { type = "1" };
+ var bodyDic = new Dictionary();
+ bodyDic.Add(ToUserId, parameter);
+ await _messageService.SentMessage(new List() { ToUserId }, title, null, bodyDic, 2, "2");
+ }
+ public async Task SendMessageSystem(string enCode)
+ {
+ var msgTemplateEntity = await _repository.AsSugarClient().Queryable().FirstAsync(x => x.EnCode == enCode && x.TemplateType == "1" && x.DeleteMark == null);
+ var bodyDic = new Dictionary();
+ bodyDic.Add(_userManager.UserId, msgTemplateEntity.Content);
+ await _messageService.SentMessage(new List() { _userManager.UserId }, msgTemplateEntity.Title, msgTemplateEntity.Content, bodyDic, 3);
+ }
#endregion
#region PrivateMethod
@@ -680,9 +697,13 @@ public class SendMessageService : ISendMessageService, IDynamicApiController, IT
if (text.IsNotEmptyOrNull())
{
// 默认站内信
- if (paramDic.ContainsKey("@taskFullName"))
+ if (paramDic.ContainsKey("@flowFullName"))
{
- text = text.Replace("@流程发起人@流程名称", paramDic["@taskFullName"]);
+ text = text.Replace("@流程名称", paramDic["@flowFullName"]);
+ }
+ if (paramDic.ContainsKey("@launchUserName"))
+ {
+ text = text.Replace("@流程发起人", paramDic["@launchUserName"]);
}
foreach (var item in paramDic.Keys)
{
diff --git a/message/Tnb.Message/Service/ShortLinkService.cs b/message/Tnb.Message/Service/ShortLinkService.cs
index 4b364574..5e5cba1f 100644
--- a/message/Tnb.Message/Service/ShortLinkService.cs
+++ b/message/Tnb.Message/Service/ShortLinkService.cs
@@ -8,6 +8,7 @@ using JNPF.Common.Security;
using JNPF.DataEncryption;
using JNPF.DependencyInjection;
using JNPF.DynamicApiController;
+using JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
using JNPF.FriendlyException;
using JNPF.Logging.Attributes;
using JNPF.Message.Entitys.Entity;
@@ -92,9 +93,15 @@ public class ShortLinkService : IShortLinkService, IDynamicApiController, ITrans
options = JNPFTenantExtensions.GetLinkToCustom(tenantId, result.data.linkList);
}
}
-
+ if (!"default".Equals(tenantId) && _tenant.MultiTenancyType.Equals("COLUMN"))
+ {
+ _sqlSugarClient.QueryFilter.AddTableFilter(it => it.TenantId == tenantId);
+ }
+ else
+ {
_sqlSugarClient.AddConnection(JNPFTenantExtensions.GetConfig(options));
_sqlSugarClient.ChangeDatabase(tenantId);
+ }
}
var entity = await _sqlSugarClient.Queryable().SingleAsync(x => x.ShortLink == shortLink && x.DeleteMark == null);
diff --git a/system/Tnb.OAuth/Dto/LoginInput.cs b/system/Tnb.OAuth/Dto/LoginInput.cs
index c89be0eb..45c3dcea 100644
--- a/system/Tnb.OAuth/Dto/LoginInput.cs
+++ b/system/Tnb.OAuth/Dto/LoginInput.cs
@@ -53,4 +53,9 @@ public class LoginInput
/// 未绑定 成功登录后 自动绑定 缓存 Key.
///
public string jnpf_ticket { get; set; }
+
+ ///
+ /// 单点登录票据.
+ ///
+ public string online_ticket { get; set; }
}
\ No newline at end of file
diff --git a/system/Tnb.OAuth/OAuthService.cs b/system/Tnb.OAuth/OAuthService.cs
index 10de81ef..f494dee3 100644
--- a/system/Tnb.OAuth/OAuthService.cs
+++ b/system/Tnb.OAuth/OAuthService.cs
@@ -35,6 +35,12 @@ using JNPF.Systems.Entitys.Model.Permission.SocialsUser;
using JNPF.Systems.Interfaces.Permission;
using JNPF.Extras.CollectiveOAuth.Models;
using JNPF.Common.Models;
+using JNPF.Common.Options;
+using Microsoft.CodeAnalysis;
+using JNPF.Common.Core.Handlers;
+using JNPF.Message.Interfaces.Message;
+using JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
+using Aop.Api.Domain;
namespace JNPF.OAuth;
@@ -45,6 +51,11 @@ namespace JNPF.OAuth;
[Route("api/[controller]")]
public class OAuthService : IDynamicApiController, ITransient
{
+ ///
+ /// 配置文档.
+ ///
+ private readonly OauthOptions _oauthOptions = App.GetConfig("OAuth", true);
+
///
/// 用户仓储.
///
@@ -125,6 +136,10 @@ public class OAuthService : IDynamicApiController, ITransient
///
private SqlSugarScope _sqlSugarClient;
+ private readonly ISendMessageService _sendMessageService;
+
+ private readonly IMHandler _imHandler;
+
///
/// 初始化一个类型的新实例.
///
@@ -138,13 +153,15 @@ public class OAuthService : IDynamicApiController, ITransient
IModuleFormService formService,
ISysConfigService sysConfigService,
ISocialsUserService socialsUserService,
+ ISendMessageService sendMessageService,
IOptions connectionOptions,
IOptions tenantOptions,
ISqlSugarClient sqlSugarClient,
IHttpContextAccessor httpContextAccessor,
ICacheManager cacheManager,
IUserManager userManager,
- IEventPublisher eventPublisher)
+ IEventPublisher eventPublisher,
+ IMHandler imHandler)
{
_captchaHandler = captchaHandler;
_userRepository = userRepository;
@@ -155,6 +172,7 @@ public class OAuthService : IDynamicApiController, ITransient
_formService = formService;
_sysConfigService = sysConfigService;
_socialsUserService = socialsUserService;
+ _sendMessageService = sendMessageService;
_connectionStrings = connectionOptions.Value;
_tenant = tenantOptions.Value;
_sqlSugarClient = (SqlSugarScope)sqlSugarClient;
@@ -162,6 +180,7 @@ public class OAuthService : IDynamicApiController, ITransient
_cacheManager = cacheManager;
_userManager = userManager;
_eventPublisher = eventPublisher;
+ _imHandler = imHandler;
}
#region Get
@@ -290,12 +309,15 @@ public class OAuthService : IDynamicApiController, ITransient
if ((loginOutput.userInfo.systemIds.Any() && !loginOutput.userInfo.systemIds.Any(x => x.id.Equals(loginOutput.userInfo.systemId))) || loginOutput.userInfo.systemId.IsNullOrEmpty())
{
- var defaultItem = loginOutput.userInfo.systemIds.Find(x => x.enCode.Equals("mainSystem"));
- if (defaultItem == null) defaultItem = loginOutput.userInfo.systemIds.FirstOrDefault();
- loginOutput.userInfo.systemId = defaultItem.id;
- defaultItem.currentSystem = true;
- await _userRepository.AsUpdateable().SetColumns(x => x.SystemId == loginOutput.userInfo.systemId).Where(x => x.Id.Equals(userId)).ExecuteCommandAsync();
- loginOutput.menuList = await _moduleService.GetUserTreeModuleList(type);
+ if (loginOutput.userInfo.systemIds.Any())
+ {
+ var defaultItem = loginOutput.userInfo.systemIds.Find(x => x.enCode.Equals("mainSystem"));
+ if (defaultItem == null) defaultItem = loginOutput.userInfo.systemIds.FirstOrDefault();
+ loginOutput.userInfo.systemId = defaultItem.id;
+ defaultItem.currentSystem = true;
+ await _userRepository.AsUpdateable().SetColumns(x => x.SystemId == loginOutput.userInfo.systemId).Where(x => x.Id.Equals(userId)).ExecuteCommandAsync();
+ loginOutput.menuList = await _moduleService.GetUserTreeModuleList(type);
+ }
}
if (!loginOutput.userInfo.systemIds.Any()) loginOutput.menuList.Clear();
@@ -357,24 +379,26 @@ public class OAuthService : IDynamicApiController, ITransient
///
///
[HttpGet("Logout")]
- public async Task Logout()
+ public async Task Logout([FromQuery] string ticket)
{
+ var tenantId = _userManager.TenantId ?? "default";
+ var userId = _userManager.UserId ?? "admim";
var httpContext = _httpContextAccessor.HttpContext;
httpContext.SignoutToSwagger();
- // 清除IM中的webSocket, modified by PhilPan 改为在IMHandle中处理
- //var list = await GetOnlineUserList();
- //if (list != null)
- //{
- // var onlineUser = list.Find(it => it.tenantId == _userManager.TenantId && it.userId == _userManager.UserId);
- // if (onlineUser != null)
- // {
- // list.RemoveAll((x) => x.connectionId == onlineUser.connectionId);
- // await SetOnlineUserList(list);
- // }
- //}
+ // 清除IM中的webSocket
+ var list = await GetOnlineUserList(tenantId);
+ if (list != null)
+ {
+ var onlineUser = list.Find(it => it.tenantId == tenantId && it.userId == userId);
+ if (onlineUser != null)
+ {
+ list.RemoveAll((x) => x.connectionId == onlineUser.connectionId);
+ await SetOnlineUserList(list, tenantId);
+ }
+ }
- await DelUserInfo();
+ await DelUserInfo(tenantId, userId);
}
#endregion
@@ -431,9 +455,15 @@ public class OAuthService : IDynamicApiController, ITransient
options = JNPFTenantExtensions.GetLinkToCustom(tenantId, result.data.linkList);
}
}
-
- _sqlSugarClient.AddConnection(JNPFTenantExtensions.GetConfig(options));
- _sqlSugarClient.ChangeDatabase(tenantId);
+ if (!"default".Equals(tenantId) && _tenant.MultiTenancyType.Equals("COLUMN"))
+ {
+ _sqlSugarClient.QueryFilter.AddTableFilter(it => it.TenantId == tenantId);
+ }
+ else
+ {
+ _sqlSugarClient.AddConnection(JNPFTenantExtensions.GetConfig(options));
+ _sqlSugarClient.ChangeDatabase(tenantId);
+ }
}
else
{
@@ -563,9 +593,13 @@ public class OAuthService : IDynamicApiController, ITransient
{ ClaimConst.CLAINMADMINISTRATOR, userAnyPwd.IsAdministrator },
{ ClaimConst.TENANTID, options.ConfigId },
{ ClaimConst.CONNECTIONCONFIG, options},
- { ClaimConst.SINGLELOGIN, (int)sysConfig.singleLogin }
+ { ClaimConst.SINGLELOGIN, (int)sysConfig.singleLogin },
+ { ClaimConst.OnlineTicket, input.online_ticket }
}, tokenTimeout);
+ // 单点登录标识缓存
+ if (_oauthOptions.Enabled) _cacheManager.Set("OnlineTicket_" + input.online_ticket, options.ConfigId);
+
// 设置Swagger自动登录
_httpContextAccessor.HttpContext.SigninToSwagger(accessToken);
@@ -635,8 +669,7 @@ public class OAuthService : IDynamicApiController, ITransient
}
}
- return new
- {
+ return new {
theme = user.Theme == null ? "classic" : user.Theme,
token = string.Format("Bearer {0}", accessToken)
};
@@ -676,6 +709,63 @@ public class OAuthService : IDynamicApiController, ITransient
await _userRepository.AsUpdateable(userInfo).ExecuteCommandAsync();
return new { code = 200, msg = "注销成功" };
}
+
+ ///
+ /// 单点登录退出.
+ ///
+ ///
+ [HttpPost("Logout/auth2")]
+ [AllowAnonymous]
+ public async Task OnlineLogout()
+ {
+ var ticket = _httpContextAccessor.HttpContext.Request.Form["ticket"];
+ var tenantId = await _cacheManager.GetAsync("OnlineTicket_" + ticket);
+ if (ticket.IsNotEmptyOrNull())
+ {
+ await _cacheManager.DelAsync("OnlineTicket_" + ticket);
+ var userId = _userManager.GetAdminUserId();
+ var userOnlineList = new List();
+ userOnlineList = await GetOnlineUserList(tenantId);
+ var userOnline = userOnlineList.Find(x => x.onlineTicket.Equals(ticket));
+ if (userOnline != null)
+ {
+ userId = userOnline.userId;
+ await _imHandler.SendMessageAsync(userOnline.connectionId, new { method = "logout", msg = "此账号已在其他地方登陆" }.ToJsonString());
+ }
+
+ // 清除IM中的webSocket
+ if (userOnlineList != null)
+ {
+ var onlineUser = userOnlineList.Find(it => it.tenantId == tenantId && it.userId == userId);
+ if (onlineUser != null)
+ {
+ userOnlineList.RemoveAll((x) => x.connectionId == onlineUser.connectionId);
+ await SetOnlineUserList(userOnlineList, tenantId);
+ }
+ }
+
+ await DelUserInfo(tenantId, userId);
+ }
+ }
+
+ ///
+ /// 密码过期提醒.
+ ///
+ ///
+ [HttpPost("updatePasswordMessage")]
+ public async Task PwdMessage()
+ {
+ var sysConfigInfo = await _sysConfigService.GetInfo();
+ // 密码修改时间.
+ var changePasswordDate = _userManager.User.ChangePasswordDate.IsNullOrEmpty() ? _userManager.User.CreatorTime : _userManager.User.ChangePasswordDate;
+ // 提醒时间
+ var remindDate = changePasswordDate.ParseToDateTime().AddDays(sysConfigInfo.updateCycle - sysConfigInfo.updateInAdvance);
+ if (sysConfigInfo.passwordIsUpdatedRegularly == 1 && remindDate < DateTime.Now)
+ {
+ await _sendMessageService.SendMessageSystem("XTXXTX001");
+ }
+ }
+
#endregion
#region PrivateMethod
@@ -740,9 +830,9 @@ public class OAuthService : IDynamicApiController, ITransient
/// 获取在线用户列表.
///
///
- private async Task> GetOnlineUserList()
+ private async Task> GetOnlineUserList(string tenantId)
{
- string cacheKey = string.Format("{0}{1}", CommonConst.CACHEKEYONLINEUSER, _userManager.ConnectionConfig.ConfigId);
+ string cacheKey = string.Format("{0}{1}", CommonConst.CACHEKEYONLINEUSER, tenantId);
return await _cacheManager.GetAsync>(cacheKey);
}
@@ -751,18 +841,18 @@ public class OAuthService : IDynamicApiController, ITransient
///
/// 在线用户列表.
///
- private async Task SetOnlineUserList(List onlineList)
+ private async Task SetOnlineUserList(List onlineList, string tenantId)
{
- string cacheKey = string.Format("{0}{1}", CommonConst.CACHEKEYONLINEUSER, _userManager.ConnectionConfig.ConfigId);
+ string cacheKey = string.Format("{0}{1}", CommonConst.CACHEKEYONLINEUSER, tenantId);
return await _cacheManager.SetAsync(cacheKey, onlineList);
}
///
/// 删除用户登录信息缓存.
///
- private async Task DelUserInfo()
+ private async Task DelUserInfo(string tenantId, string userId)
{
- string cacheKey = string.Format("{0}{1}_{2}", CommonConst.CACHEKEYUSER, _userManager.ConnectionConfig.ConfigId, _userManager.UserId);
+ string cacheKey = string.Format("{0}:{1}:{2}", tenantId, CommonConst.CACHEKEYUSER, userId);
return await _cacheManager.DelAsync(cacheKey);
}
@@ -1109,15 +1199,25 @@ public class OAuthService : IDynamicApiController, ITransient
{
var loginConfigModel = new SocialsLoginConfigModel();
- // 追加第三方登录配置
- var loginList = _socialsUserService.GetLoginList(CommonConst.PARAMS_JNPF_TICKET.ToUpper());
- if (loginList == null) return loginConfigModel;
- if (loginList.Any())
+ if (_oauthOptions.Enabled)
{
- loginConfigModel.socialsList = loginList.ToObject>();
- loginConfigModel.redirect = false;
+ var url = _oauthOptions.LoginPath + "/" + _oauthOptions.DefaultSSO;
+ loginConfigModel.redirect = true;
+ loginConfigModel.url = url;
loginConfigModel.ticketParams = CommonConst.PARAMS_JNPF_TICKET;
}
+ else
+ {
+ // 追加第三方登录配置
+ var loginList = _socialsUserService.GetLoginList(CommonConst.PARAMS_JNPF_TICKET.ToUpper());
+ if (loginList == null) return loginConfigModel;
+ if (loginList.Any())
+ {
+ loginConfigModel.socialsList = loginList.ToObject>();
+ loginConfigModel.redirect = false;
+ loginConfigModel.ticketParams = CommonConst.PARAMS_JNPF_TICKET;
+ }
+ }
return loginConfigModel;
}
@@ -1132,10 +1232,10 @@ public class OAuthService : IDynamicApiController, ITransient
public dynamic GetTicket()
{
SocialsLoginTicketModel ticketModel = new SocialsLoginTicketModel();
- var curDate = DateTime.Now.AddMinutes(5); // 默认过期5分钟.
+ var curDate = DateTime.Now.AddMinutes(_oauthOptions.TicketTimeout); // 默认过期5分钟.
ticketModel.ticketTimeout = curDate.ParseToUnixTime();
- var key = "SocialsLogin_" + Yitter.IdGenerator.YitIdHelper.NextId().ToString();
- _cacheManager.Set(key, ticketModel.ToJsonString(), TimeSpan.FromMinutes(5));
+ var key = "SocialsLogin_" + SnowflakeIdHelper.NextId();
+ _cacheManager.Set(key, ticketModel.ToJsonString(), TimeSpan.FromMinutes(_oauthOptions.TicketTimeout));
return key;
}
@@ -1158,4 +1258,264 @@ public class OAuthService : IDynamicApiController, ITransient
}
#endregion
+
+ #region 单点登录.
+
+ ///
+ /// 单点登录接口.
+ ///
+ ///
+ ///
+ [HttpGet("Login/{type}")]
+ [AllowAnonymous]
+ [IgnoreLog]
+ [NonUnify]
+ public async Task LoginByType(string type, [FromQuery] Dictionary input)
+ {
+ #region Cas
+ //if (type.ToLower().Equals("cas"))
+ //{
+ // var ticket = input.ContainsKey(CommonConst.PARAMS_JNPF_TICKET) ? input[CommonConst.PARAMS_JNPF_TICKET].ToString() : string.Empty;
+ // var ticketModel = _cacheManager.Get(ticket);
+ // if (ticketModel == null) return "登录票据已失效";
+
+ // var casTicket = input.ContainsKey(CommonConst.CAS_Ticket) ? input[CommonConst.CAS_Ticket].ToString() : string.Empty;
+ // if (casTicket.IsNotEmptyOrNull())
+ // {
+
+ // }
+ // else
+ // {
+ // var loginUrl = _oauthOptions.SSO.Cas.ServerLoginUrl;
+ // //http://sso.maxkey.top:8527/sign/authz/cas/?service=http://sa-oauth-client.demo.maxkey.top:8002
+
+ // loginUrl = Extras.CollectiveOAuth.Utils.UrlBuilder.fromBaseUrl(loginUrl)
+ // .queryParam("service", _oauthOptions.LoginPath + "/cas")
+ // .queryParam(CommonConst.PARAMS_JNPF_TICKET, ticket)
+ // .build();
+ // _httpContextAccessor.HttpContext.Response.Redirect(loginUrl);
+ // }
+ //}
+ #endregion
+
+ if (type.ToLower().Equals("auth2"))
+ {
+ var ticket = string.Empty;
+ if (input.ContainsKey(CommonConst.PARAMS_JNPF_TICKET) && input[CommonConst.PARAMS_JNPF_TICKET].IsNotEmptyOrNull())
+ {
+ ticket = input[CommonConst.PARAMS_JNPF_TICKET];
+ var ticketModel = _cacheManager.Get(ticket);
+ if (ticketModel == null) return "登录票据已失效";
+ }
+
+ var code = input.ContainsKey(CommonConst.Code) ? input[CommonConst.Code] : string.Empty;
+
+ // 接受CODE 进行登录
+ if (code.IsNotEmptyOrNull())
+ {
+ try
+ {
+ await loginByCode(code, ticket);
+ }
+ catch (Exception e)
+ {
+ // 更新登录结果
+ return e.Message;
+ }
+ }
+ else
+ {
+ redirectLogin(ticket);
+ }
+ }
+
+ return null;
+ }
+
+ ///
+ /// 跳转单点登录页面.
+ ///
+ protected void redirectLogin(string ticket)
+ {
+ var loginUrl = _oauthOptions.SSO.Auth2.AuthorizeUrl;
+ var tmpAuthCallbackUrl = _oauthOptions.LoginPath + "/auth2";
+ //http://sso.maxkey.top:8527/sign/authz/oauth/v20/authorize?response_type=code&client_id=745057899234983936&redirect_uri=http://sa-oauth-client.demo.maxkey.top:8002/&scope=all
+
+ if (ticket.IsNotEmptyOrNull())
+ {
+ tmpAuthCallbackUrl = Extras.CollectiveOAuth.Utils.UrlBuilder.fromBaseUrl(tmpAuthCallbackUrl)
+ .queryParam(CommonConst.PARAMS_JNPF_TICKET, ticket)
+ .build();
+ }
+
+ loginUrl = Extras.CollectiveOAuth.Utils.UrlBuilder.fromBaseUrl(loginUrl)
+ .queryParam("response_type", CommonConst.Code)
+ .queryParam("client_id", _oauthOptions.SSO.Auth2.ClientId)
+ .queryParam("scope", "read")
+ .queryParam("redirect_uri", tmpAuthCallbackUrl)
+ .build();
+
+ _httpContextAccessor.HttpContext.Response.Redirect(loginUrl);
+ }
+
+ ///
+ /// Oauth2登录.
+ ///
+ ///
+ ///
+ protected async Task loginByCode(string code, string ticket)
+ {
+ var token = await getAccessToken(code);
+ var remoteUserInfo = await getRemoteInfo(token);
+ //var userId = remoteUserInfo.getOrDefault("accounts.username", remoteUserInfo["username"]).ToString();
+ var userId = remoteUserInfo.ContainsKey("accounts.username") ? remoteUserInfo["accounts.username"].ToString() : remoteUserInfo["username"].ToString();
+ var userAccount = string.Empty;
+ if (_tenant.MultiTenancy)
+ {
+ var instId = remoteUserInfo["institution"].ToString();
+ userAccount = instId + "@" + userId;
+ }
+ else
+ {
+ userAccount = userId;
+ }
+
+ // 登录账号
+ var loginInput = await GetUserInfoByUserAccount(userAccount);
+ loginInput.online_ticket = remoteUserInfo["online_ticket"].ToString();
+ var loginRes = await Login(loginInput);
+
+ var jnpfTicket = _cacheManager.Get(ticket);
+ if (jnpfTicket.IsNotEmptyOrNull())
+ {
+ // 修改 缓存 状态
+ jnpfTicket.status = (int)SocialsLoginTicketStatus.Success;
+ jnpfTicket.value = loginRes.token;
+ _cacheManager.Set(ticket, jnpfTicket.ToJsonString(), TimeSpan.FromMinutes(_oauthOptions.TicketTimeout));
+ }
+ else
+ {
+ var url = string.Format("{0}?token={1}&theme={2}", _oauthOptions.SucessFrontUrl, loginRes.token, loginRes.theme);
+ _httpContextAccessor.HttpContext.Response.Redirect(url);
+ }
+ }
+
+ ///
+ /// 获取OAUTH2 AccessToken.
+ ///
+ ///
+ ///
+ private async Task getAccessToken(string code)
+ {
+ var reqUrl = _oauthOptions.SSO.Auth2.AccessTokenUrl
+ .AddUrlQuery(string.Format("grant_type={0}", "authorization_code"))
+ .AddUrlQuery(string.Format("client_id={0}", _oauthOptions.SSO.Auth2.ClientId))
+ .AddUrlQuery(string.Format("client_secret={0}", _oauthOptions.SSO.Auth2.ClientSecret))
+ .AddUrlQuery(string.Format("redirect_uri={0}", _oauthOptions.LoginPath + "/auth2"))
+ .AddUrlQuery(string.Format("code={0}", code));
+
+ var response = await reqUrl.GetAsStringAsync();
+ Dictionary result = null;
+ try
+ {
+ result = response.ToObject>();
+ }
+ catch (Exception e)
+ {
+ // log.error("解析Auth2 access_token失败", e);
+ }
+
+ if (result == null || !result.ContainsKey("access_token"))
+ {
+ throw new Exception("Auth2: 获取access_token失败");
+ }
+
+ var access_token = result["access_token"].ToString();
+
+ // log.debug("Auth2 Token: {}", access_token);
+ return access_token;
+ }
+
+ ///
+ /// 获取用户信息.
+ ///
+ ///
+ ///
+ private async Task> getRemoteInfo(string access_token)
+ {
+ var reqUrl = _oauthOptions.SSO.Auth2.UserInfoUrl
+ .AddUrlQuery(string.Format("access_token={0}", access_token));
+ var response = await reqUrl.GetAsStringAsync();
+
+ Dictionary result = null;
+ try
+ {
+ // log.debug("Auth2 User: {}", response);
+ result = response.ToObject>();
+ }
+ catch (Exception e)
+ {
+ // log.error("解析Auth2 用户信息失败", e);
+ }
+
+ if (result == null || !result.ContainsKey("username"))
+ {
+ // log.error(response);
+ throw new Exception("Auth2: 获取远程用户信息失败");
+ }
+
+ return result;
+ }
+
+ private async Task GetUserInfoByUserAccount(string account)
+ {
+ ConnectionConfigOptions options = JNPFTenantExtensions.GetLinkToOrdinary(_connectionStrings.ConfigId, _connectionStrings.DBName);
+ UserAgent userAgent = new UserAgent(App.HttpContext);
+ if (_tenant.MultiTenancy)
+ {
+ // 分割账号
+ var tenantAccount = account.Split('@');
+ var tenantId = tenantAccount.FirstOrDefault();
+ if (tenantAccount.Length == 1)
+ account = "admin";
+ else
+ account = tenantAccount[1];
+
+ var interFace = string.Format("{0}{1}", _tenant.MultiTenancyDBInterFace, tenantId);
+ var response = await interFace.GetAsStringAsync();
+ var result = response.ToObject>();
+ if (result.code != 200)
+ {
+ throw Oops.Oh(result.msg);
+ }
+ else if (result.data.dotnet == null && result.data.linkList == null)
+ {
+ throw Oops.Oh(ErrorCode.D1025);
+ }
+ else
+ {
+ if (result.data.linkList == null || result.data.linkList?.Count == 0)
+ {
+ options = JNPFTenantExtensions.GetLinkToOrdinary(tenantId, result.data.dotnet);
+ }
+ else if (result.data.dotnet == null)
+ {
+ options = JNPFTenantExtensions.GetLinkToCustom(tenantId, result.data.linkList);
+ }
+ }
+
+ _sqlSugarClient.AddConnection(JNPFTenantExtensions.GetConfig(options));
+ _sqlSugarClient.ChangeDatabase(tenantId);
+ }
+
+ var userEntity = _sqlSugarClient.Queryable().Single(u => u.Account == account && u.DeleteMark == null);
+ return new LoginInput()
+ {
+ account = userEntity.Account,
+ password = userEntity.Password,
+ isSocialsLoginCallBack = true
+ };
+ }
+
+ #endregion
}
\ No newline at end of file
diff --git a/system/Tnb.OAuth/Tnb.OAuth.csproj b/system/Tnb.OAuth/Tnb.OAuth.csproj
index 1640baae..af2ae6c7 100644
--- a/system/Tnb.OAuth/Tnb.OAuth.csproj
+++ b/system/Tnb.OAuth/Tnb.OAuth.csproj
@@ -11,6 +11,7 @@
+
diff --git a/system/Tnb.Systems.Entitys/Dto/Permission/User/GetDefaultCurrentValueInput.cs b/system/Tnb.Systems.Entitys/Dto/Permission/User/GetDefaultCurrentValueInput.cs
new file mode 100644
index 00000000..85c0a9d6
--- /dev/null
+++ b/system/Tnb.Systems.Entitys/Dto/Permission/User/GetDefaultCurrentValueInput.cs
@@ -0,0 +1,41 @@
+using System.Text.Json.Serialization;
+using JNPF.DependencyInjection;
+
+namespace JNPF.Systems.Entitys.Dto.User;
+
+///
+/// 当前用户默认值信息输出.
+///
+[SuppressSniffer]
+public class GetDefaultCurrentValueInput
+{
+ ///
+ /// 部门Ids.
+ ///
+ public List DepartIds { get; set; }
+
+ ///
+ /// 用户Ids.
+ ///
+ public List UserIds { get; set; }
+
+ ///
+ /// 角色Ids.
+ ///
+ public List RoleIds { get; set; }
+
+ ///
+ /// 岗位Ids.
+ ///
+ public List PositionIds { get; set; }
+
+ ///
+ /// 分组Ids.
+ ///
+ public List GroupIds { get; set; }
+
+ ///
+ /// .
+ ///
+ public string Keyword { get; set; }
+}
\ No newline at end of file
diff --git a/system/Tnb.Systems.Entitys/Dto/System/CommonWords/CommonWordsInput.cs b/system/Tnb.Systems.Entitys/Dto/System/CommonWords/CommonWordsInput.cs
new file mode 100644
index 00000000..65e810fe
--- /dev/null
+++ b/system/Tnb.Systems.Entitys/Dto/System/CommonWords/CommonWordsInput.cs
@@ -0,0 +1,40 @@
+namespace JNPF.Systems.Entitys.Dto.System.CommonWords
+{
+ public class CommonWordsInput
+ {
+ ///
+ /// 自然主键.
+ ///
+ public string id { get; set; }
+
+ ///
+ /// 应用id.
+ ///
+ public List systemIds { get; set; } = new List();
+
+ ///
+ /// 应用名称.
+ ///
+ public List systemNames { get; set; } = new List();
+
+ ///
+ /// 常用语.
+ ///
+ public string commonWordsText { get; set; }
+
+ ///
+ /// 常用语类型(0:系统,1:个人).
+ ///
+ public int commonWordsType { get; set; }
+
+ ///
+ /// 排序.
+ ///
+ public long sortCode { get; set; }
+
+ ///
+ /// 有效标志.
+ ///
+ public int? enabledMark { get; set; }
+ }
+}
diff --git a/system/Tnb.Systems.Entitys/Dto/System/CommonWords/CommonWordsOutput.cs b/system/Tnb.Systems.Entitys/Dto/System/CommonWords/CommonWordsOutput.cs
new file mode 100644
index 00000000..68b3b857
--- /dev/null
+++ b/system/Tnb.Systems.Entitys/Dto/System/CommonWords/CommonWordsOutput.cs
@@ -0,0 +1,39 @@
+namespace JNPF.Systems.Entitys.Dto.System.CommonWords;
+
+public class CommonWordsOutput
+{
+ ///
+ /// 自然主键.
+ ///
+ public string id { get; set; }
+
+ ///
+ /// 应用id.
+ ///
+ public string systemId { get; set; }
+
+ ///
+ /// 应用名称.
+ ///
+ public string systemNames { get; set; }
+
+ ///
+ /// 常用语.
+ ///
+ public string commonWordsText { get; set; }
+
+ ///
+ /// 常用语类型(0:系统,1:个人).
+ ///
+ public int commonWordsType { get; set; }
+
+ ///
+ /// 排序.
+ ///
+ public long sortCode { get; set; }
+
+ ///
+ /// 有效标志.
+ ///
+ public int? enabledMark { get; set; }
+}
diff --git a/system/Tnb.Systems.Entitys/Dto/System/PrintDev/PrintDevCrInput.cs b/system/Tnb.Systems.Entitys/Dto/System/PrintDev/PrintDevCrInput.cs
index 5a4dfc3c..ce7d9725 100644
--- a/system/Tnb.Systems.Entitys/Dto/System/PrintDev/PrintDevCrInput.cs
+++ b/system/Tnb.Systems.Entitys/Dto/System/PrintDev/PrintDevCrInput.cs
@@ -62,4 +62,9 @@ public class PrintDevCrInput
/// 打印模板.
///
public string printTemplate { get; set; }
+
+ ///
+ /// 纸张参数.
+ ///
+ public string pageParam { get; set; }
}
\ No newline at end of file
diff --git a/system/Tnb.Systems.Entitys/Dto/System/PrintDev/PrintDevInfoOutput.cs b/system/Tnb.Systems.Entitys/Dto/System/PrintDev/PrintDevInfoOutput.cs
index 4aa37d1a..253381df 100644
--- a/system/Tnb.Systems.Entitys/Dto/System/PrintDev/PrintDevInfoOutput.cs
+++ b/system/Tnb.Systems.Entitys/Dto/System/PrintDev/PrintDevInfoOutput.cs
@@ -67,4 +67,9 @@ public class PrintDevInfoOutput
/// 打印模板.
///
public string printTemplate { get; set; }
+
+ ///
+ /// 纸张参数.
+ ///
+ public string pageParam { get; set; }
}
\ No newline at end of file
diff --git a/system/Tnb.Systems.Entitys/Dto/System/PrintDev/PrintDevSqlDataQuery.cs b/system/Tnb.Systems.Entitys/Dto/System/PrintDev/PrintDevSqlDataQuery.cs
index e963a7c7..dfa39350 100644
--- a/system/Tnb.Systems.Entitys/Dto/System/PrintDev/PrintDevSqlDataQuery.cs
+++ b/system/Tnb.Systems.Entitys/Dto/System/PrintDev/PrintDevSqlDataQuery.cs
@@ -17,4 +17,9 @@ public class PrintDevSqlDataQuery
/// 参数.
///
public string formId { get; set; }
+
+ ///
+ /// 模板id.
+ ///
+ public List ids { get; set; }
}
\ No newline at end of file
diff --git a/system/Tnb.Systems.Entitys/Dto/System/PrintLog/PrintLogOutuut.cs b/system/Tnb.Systems.Entitys/Dto/System/PrintLog/PrintLogOutuut.cs
new file mode 100644
index 00000000..dc0bb802
--- /dev/null
+++ b/system/Tnb.Systems.Entitys/Dto/System/PrintLog/PrintLogOutuut.cs
@@ -0,0 +1,34 @@
+namespace JNPF.Systems.Entitys.Dto.System.PrintLog;
+
+public class PrintLogOutuut
+{
+ ///
+ /// id.
+ ///
+ public string id { get; set; }
+
+ ///
+ /// 打印人.
+ ///
+ public string printMan { get; set; }
+
+ ///
+ /// 打印时间.
+ ///
+ public DateTime? printTime { get; set; }
+
+ ///
+ /// 打印条数.
+ ///
+ public int? printNum { get; set; }
+
+ ///
+ /// 打印功能名称.
+ ///
+ public string printTitle { get; set; }
+
+ ///
+ /// 打印模板id.
+ ///
+ public string printId { get; set; }
+}
diff --git a/system/Tnb.Systems.Entitys/Dto/System/PrintLog/PrintLogQuery.cs b/system/Tnb.Systems.Entitys/Dto/System/PrintLog/PrintLogQuery.cs
new file mode 100644
index 00000000..7c6fd5ac
--- /dev/null
+++ b/system/Tnb.Systems.Entitys/Dto/System/PrintLog/PrintLogQuery.cs
@@ -0,0 +1,16 @@
+using JNPF.Common.Filter;
+
+namespace JNPF.Systems.Entitys.Dto.System.PrintLog;
+
+public class PrintLogQuery : PageInputBase
+{
+ ///
+ /// 开始时间.
+ ///
+ public long? startTime { get; set; }
+
+ ///
+ /// 结束时间.
+ ///
+ public long? endTime { get; set; }
+}
diff --git a/system/Tnb.Systems.Entitys/Dto/System/SysConfig/SysConfigOutput.cs b/system/Tnb.Systems.Entitys/Dto/System/SysConfig/SysConfigOutput.cs
index 277f0394..f9499516 100644
--- a/system/Tnb.Systems.Entitys/Dto/System/SysConfig/SysConfigOutput.cs
+++ b/system/Tnb.Systems.Entitys/Dto/System/SysConfig/SysConfigOutput.cs
@@ -346,4 +346,71 @@ public class SysConfigOutput
/// 链接点击几次后失效.
///
public int unClickNum { get; set; }
+
+ #region 密码策略
+ ///
+ /// 密码定期更新开关.
+ ///
+ public int passwordIsUpdatedRegularly { get; set; }
+
+ ///
+ /// 更新周期.
+ ///
+ public int updateCycle { get; set; }
+
+ ///
+ /// 提前N天提醒更新.
+ ///
+ public int updateInAdvance { get; set; }
+
+ ///
+ /// 密码强度限制开关.
+ ///
+ public int passwordStrengthLimit { get; set; }
+
+ ///
+ /// 最小长度开关.
+ ///
+ public int passwordLengthMin { get; set; }
+
+ ///
+ /// 密码最小长度限制.
+ ///
+ public int passwordLengthMinNumber { get; set; }
+
+ ///
+ /// 是否包含数字.
+ ///
+ public int containsNumbers { get; set; }
+
+ ///
+ /// 是否包含小写字母.
+ ///
+ public int includeLowercaseLetters { get; set; }
+
+ ///
+ /// 是否包含大写字母.
+ ///
+ public int includeUppercaseLetters { get; set; }
+
+ ///
+ /// 是否包含字符.
+ ///
+ public int containsCharacters { get; set; }
+
+ ///
+ /// 是否禁用旧密码开关.
+ ///
+ public int disableOldPassword { get; set; }
+
+ ///
+ /// 禁用旧密码个数.
+ ///
+ public int disableTheNumberOfOldPasswords { get; set; }
+
+ ///
+ /// 初始密码强制修改开关.
+ ///
+ public int mandatoryModificationOfInitialPassword { get; set; }
+ #endregion
}
\ No newline at end of file
diff --git a/system/Tnb.Systems.Entitys/Dto/System/System/SystemQuery.cs b/system/Tnb.Systems.Entitys/Dto/System/System/SystemQuery.cs
new file mode 100644
index 00000000..c5764e12
--- /dev/null
+++ b/system/Tnb.Systems.Entitys/Dto/System/System/SystemQuery.cs
@@ -0,0 +1,11 @@
+using JNPF.Common.Filter;
+
+namespace JNPF.Systems.Entitys.Dto.System.System;
+
+public class SystemQuery : KeywordInput
+{
+ ///
+ /// 开启 1 0 禁用.
+ ///
+ public string enableMark { get; set; }
+}
diff --git a/system/Tnb.Systems.Entitys/Entity/Permission/UserOldPasswordEntity.cs b/system/Tnb.Systems.Entitys/Entity/Permission/UserOldPasswordEntity.cs
new file mode 100644
index 00000000..bf474a97
--- /dev/null
+++ b/system/Tnb.Systems.Entitys/Entity/Permission/UserOldPasswordEntity.cs
@@ -0,0 +1,47 @@
+using JNPF.Common.Contracts;
+using SqlSugar;
+
+namespace JNPF.Systems.Entitys.Entity.Permission;
+
+///
+/// 用户旧密码记录表.
+///
+[SugarTable("BASE_USER_OLD_PASSWORD")]
+public class UserOldPasswordEntity : EntityBase
+{
+ ///
+ /// 用户ID.
+ ///
+ [SugarColumn(ColumnName = "F_USERID")]
+ public string UserId { get; set; }
+
+ ///
+ /// 用户ID.
+ ///
+ [SugarColumn(ColumnName = "F_Account")]
+ public string Account { get; set; }
+
+ ///
+ /// 账户.
+ ///
+ [SugarColumn(ColumnName = "F_OldPassword")]
+ public string OldPassword { get; set; }
+
+ ///
+ /// 秘钥.
+ ///
+ [SugarColumn(ColumnName = "F_Secretkey")]
+ public string Secretkey { get; set; }
+
+ ///
+ /// 创建时间.
+ ///
+ [SugarColumn(ColumnName = "F_CreatorTime")]
+ public DateTime CreatorTime { get; set; }
+
+ ///
+ /// 租户ID.
+ ///
+ [SugarColumn(ColumnName = "F_TenantId")]
+ public string TenantId { get; set; }
+}
diff --git a/system/Tnb.Systems.Entitys/Entity/System/CommonWordsEntity.cs b/system/Tnb.Systems.Entitys/Entity/System/CommonWordsEntity.cs
new file mode 100644
index 00000000..c5b9bbf1
--- /dev/null
+++ b/system/Tnb.Systems.Entitys/Entity/System/CommonWordsEntity.cs
@@ -0,0 +1,45 @@
+using JNPF.Common.Contracts;
+using SqlSugar;
+
+namespace JNPF.Systems.Entitys.Entity.System;
+
+///
+/// 常用语
+/// 版 本:V3.2
+/// 版 权:引迈信息技术有限公司(https://www.jnpfsoft.com)
+/// 作 者:JNPF开发平台组
+/// 日 期:2021-06-01.
+///
+[SugarTable("BASE_COMMONWORDS")]
+public class CommonWordsEntity : CLDEntityBase
+{
+ ///
+ /// 应用id.
+ ///
+ [SugarColumn(ColumnName = "F_SYSTEMIDS")]
+ public string SystemIds { get; set; }
+
+ ///
+ /// 应用名称.
+ ///
+ [SugarColumn(ColumnName = "F_SYSTEMNAMES")]
+ public string SystemNames { get; set; }
+
+ ///
+ /// 常用语.
+ ///
+ [SugarColumn(ColumnName = "F_COMMONWORDSTEXT")]
+ public string CommonWordsText { get; set; }
+
+ ///
+ /// 常用语类型(0:系统,1:个人).
+ ///
+ [SugarColumn(ColumnName = "F_COMMONWORDSTYPE")]
+ public int CommonWordsType { get; set; }
+
+ ///
+ /// 排序.
+ ///
+ [SugarColumn(ColumnName = "F_SORTCODE")]
+ public long SortCode { get; set; }
+}
diff --git a/system/Tnb.Systems.Entitys/Entity/System/PrintDevEntity.cs b/system/Tnb.Systems.Entitys/Entity/System/PrintDevEntity.cs
index 932d71d7..e08e062d 100644
--- a/system/Tnb.Systems.Entitys/Entity/System/PrintDevEntity.cs
+++ b/system/Tnb.Systems.Entitys/Entity/System/PrintDevEntity.cs
@@ -73,4 +73,6 @@ public class PrintDevEntity : CLDEntityBase
///
[SugarColumn(ColumnName = "F_PRINTTEMPLATE")]
public string PrintTemplate { get; set; }
+ [SugarColumn(ColumnName = "F_PAGEPARAM")]
+ public string PageParam { get; set; }
}
\ No newline at end of file
diff --git a/system/Tnb.Systems.Entitys/Entity/System/PrintLogEntity.cs b/system/Tnb.Systems.Entitys/Entity/System/PrintLogEntity.cs
new file mode 100644
index 00000000..d309b5af
--- /dev/null
+++ b/system/Tnb.Systems.Entitys/Entity/System/PrintLogEntity.cs
@@ -0,0 +1,47 @@
+using JNPF.Common.Const;
+using JNPF.Common.Contracts;
+using SqlSugar;
+
+namespace JNPF.Systems.Entitys.Entity.System;
+
+///
+/// 打印模板日志
+/// 版 本:V3.2
+/// 版 权:引迈信息技术有限公司(https://www.jnpfsoft.com)
+/// 作 者:JNPF开发平台组
+/// 日 期:2021-06-01.
+///
+[SugarTable("BASE_PRINT_LOG")]
+[Tenant(ClaimConst.TENANTID)]
+public class PrintLogEntity : EntityBase
+{
+ ///
+ /// 打印人.
+ ///
+ [SugarColumn(ColumnName = "F_PrintMan")]
+ public string PrintMan { get; set; }
+
+ ///
+ /// 打印时间.
+ ///
+ [SugarColumn(ColumnName = "F_PrintTime")]
+ public DateTime? PrintTime { get; set; }
+
+ ///
+ /// 打印条数.
+ ///
+ [SugarColumn(ColumnName = "F_PrintNum")]
+ public int? PrintNum { get; set; }
+
+ ///
+ /// 打印功能名称.
+ ///
+ [SugarColumn(ColumnName = "F_PrintTitle")]
+ public string PrintTitle { get; set; }
+
+ ///
+ /// 打印模板id.
+ ///
+ [SugarColumn(ColumnName = "F_PrintId")]
+ public string PrintId { get; set; }
+}
diff --git a/system/Tnb.Systems.Entitys/Model/Permission/User/SSOUserInfoModel.cs b/system/Tnb.Systems.Entitys/Model/Permission/User/SSOUserInfoModel.cs
new file mode 100644
index 00000000..4bb35de7
--- /dev/null
+++ b/system/Tnb.Systems.Entitys/Model/Permission/User/SSOUserInfoModel.cs
@@ -0,0 +1,201 @@
+namespace JNPF.Systems.Entitys.Model.Permission.User;
+
+public class UserInfo
+{
+ private static readonly long serialVersionUID = 6402443942083382236L;
+
+ public static readonly string CLASS_TYPE = "UserInfo";
+
+ public static readonly string DEFAULT_PASSWORD_SUFFIX = "MaxKey@888";
+
+ string sessionId { get; set; }
+
+ public string id { get; set; }
+ public string username { get; set; }
+ public string password { get; set; }
+ public string decipherable { get; set; }
+ public string sharedSecret { get; set; }
+ public string sharedCounter { get; set; }
+ /**
+ * "Employee", "Supplier","Dealer","Contractor",Partner,Customer "Intern",
+ * "Temp", "External", and "Unknown" .
+ */
+ public string userType { get; set; }
+
+ public string userState { get; set; }
+
+ public string windowsAccount { get; set; }
+
+ // for user name
+ public string displayName { get; set; }
+ public string nickName { get; set; }
+ public string nameZhSpell { get; set; }
+ public string nameZhShortSpell { get; set; }
+ public string givenName { get; set; }
+ public string middleName { get; set; }
+ public string familyName { get; set; }
+ public string honorificPrefix { get; set; }
+ public string honorificSuffix { get; set; }
+ public string formattedName { get; set; }
+
+ public int married { get; set; }
+ public int gender { get; set; }
+ public string birthDate { get; set; }
+ public byte[] picture { get; set; }
+ public string pictureBase64 { get; set; }
+ public string pictureId { get; set; }
+ public int idType { get; set; }
+ public string idCardNo { get; set; }
+ public string webSite { get; set; }
+ public string startWorkDate { get; set; }
+
+ // for security
+ public int authnType { get; set; }
+ public string email { get; set; }
+
+ public int emailVerified { get; set; }
+ public string mobile { get; set; }
+
+ public int mobileVerified { get; set; }
+
+ public string passwordQuestion { get; set; }
+
+ public string passwordAnswer { get; set; }
+ // for apps login public
+ public int appLoginAuthnType { get; set; }
+ public string appLoginPassword { get; set; }
+ public string protectedApps { get; set; }
+ public Dictionary protectedAppsMap { get; set; }
+
+ public string passwordLastSetTime { get; set; }
+ public int badPasswordCount { get; set; }
+ public string badPasswordTime { get; set; }
+ public string unLockTime { get; set; }
+ public int isLocked { get; set; }
+ public string lastLoginTime { get; set; }
+ public string lastLoginIp { get; set; }
+ public string lastLogoffTime { get; set; }
+ public int passwordSetType { get; set; }
+ public int loginCount { get; set; }
+ public string regionHistory { get; set; }
+ public string passwordHistory { get; set; }
+
+ public string locale { get; set; }
+ public string timeZone { get; set; }
+ public string preferredLanguage { get; set; }
+
+ // for work
+ public string workCountry { get; set; }
+ public string workRegion { get; set; }// province
+ public string workLocality { get; set; }// city
+ public string workStreetAddress { get; set; }
+ public string workAddressFormatted { get; set; }
+ public string workEmail { get; set; }
+ public string workPhoneNumber { get; set; }
+ public string workPostalCode { get; set; }
+ public string workFax { get; set; }
+
+ public string workOfficeName { get; set; }
+ // for home
+ public string homeCountry { get; set; }
+ public string homeRegion { get; set; }// province
+ public string homeLocality { get; set; }// city
+ public string homeStreetAddress { get; set; }
+ public string homeAddressFormatted { get; set; }
+ public string homeEmail { get; set; }
+ public string homePhoneNumber { get; set; }
+ public string homePostalCode { get; set; }
+ public string homeFax { get; set; }
+ // for company
+ public string employeeNumber { get; set; }
+ public string costCenter { get; set; }
+ public string organization { get; set; }
+ public string division { get; set; }
+ public string departmentId { get; set; }
+ public string department { get; set; }
+ public string jobTitle { get; set; }
+ public string jobLevel { get; set; }
+ public string managerId { get; set; }
+ public string manager { get; set; }
+ public string assistantId { get; set; }
+ public string assistant { get; set; }
+ public string entryDate { get; set; }
+ public string quitDate { get; set; }
+
+ // for social contact
+ public string defineIm { get; set; }
+ public int weixinFollow { get; set; }
+
+ public string theme { get; set; }
+ /*
+ * for extended Attribute from userType extraAttribute for database
+ * extraAttributeName & extraAttributeValue for page submit
+ */
+ public string extraAttribute { get; set; }
+ public string extraAttributeName { get; set; }
+ public string extraAttributeValue { get; set; }
+ public Dictionary extraAttributeMap { get; set; }
+
+ public int online { get; set; }
+
+ public string ldapDn { get; set; }
+
+ public int gridList { get; set; }
+
+ public string createdBy { get; set; }
+ public string createdDate { get; set; }
+ public string modifiedBy { get; set; }
+ public string modifiedDate { get; set; }
+ public int status { get; set; }
+ string description { get; set; }
+
+ ///
+ /// 租户Id.
+ ///
+ public string instId { get; set; }
+
+ private string instName;
+
+ string syncId { get; set; }
+
+ string syncName { get; set; }
+
+ string originId { get; set; }
+
+ string originId2 { get; set; }
+
+ string gradingUserId { get; set; }
+
+ public override string ToString()
+ {
+ return "UserInfo{" +
+ "id='" + id + '\'' +
+ ", username='" + username + '\'' +
+ '}';
+ }
+}
+
+public class MqMessage
+{
+ public string id { get; set; }
+ public string topic { get; set; }
+ public string actionType { get; set; }
+ public string sendTime { get; set; }
+ public object content { get; set; }
+ public UserInfo userInfo { get; set; }
+
+ public MqMessage()
+ {
+ }
+
+ public MqMessage(string id, string topic, string actionType, string sendTime, object content, UserInfo userInfo)
+ {
+ this.id = id;
+ this.topic = topic;
+ this.actionType = actionType;
+ this.sendTime = sendTime;
+ this.content = content;
+ this.userInfo = userInfo;
+ }
+}
+
diff --git a/system/Tnb.Systems.Interfaces/Permission/IUsersService.cs b/system/Tnb.Systems.Interfaces/Permission/IUsersService.cs
index bf333805..a352eb73 100644
--- a/system/Tnb.Systems.Interfaces/Permission/IUsersService.cs
+++ b/system/Tnb.Systems.Interfaces/Permission/IUsersService.cs
@@ -86,4 +86,5 @@ public interface IUsersService
/// select 选择字段表达式.
///
Task> GetUserListByExp(Expression> expression, Expression> select);
+ Task Receive(string message);
}
\ No newline at end of file
diff --git a/system/Tnb.Systems/Common/FileService.cs b/system/Tnb.Systems/Common/FileService.cs
index 3cfdb77d..cb62fdfa 100644
--- a/system/Tnb.Systems/Common/FileService.cs
+++ b/system/Tnb.Systems/Common/FileService.cs
@@ -1,4 +1,5 @@
-using System.Security.Cryptography;
+using System.IO.Compression;
+using System.Security.Cryptography;
using System.Text;
using System.Web;
using JNPF.Common.Captcha.General;
@@ -80,7 +81,7 @@ public class FileService : IFileService, IDynamicApiController, ITransient
///
///
[HttpGet("Uploader/Preview")]
- public async Task Preview(string fileName)
+ public async Task Preview(string fileName, string fileDownloadUrl)
{
string[]? typeList = new string[] { "doc", "docx", "xls", "xlsx", "ppt", "pptx", "pdf", "jpg", "jpeg", "gif", "png", "bmp" };
string? type = fileName.Split('.').LastOrDefault();
@@ -92,7 +93,7 @@ public class FileService : IFileService, IDynamicApiController, ITransient
switch (_appOptions.PreviewType)
{
case PreviewType.kkfile:
- previewUrl = KKFileUploaderPreview(fileName);
+ previewUrl = KKFileUploaderPreview(fileName, fileDownloadUrl);
break;
case PreviewType.yozo:
previewUrl = await YoZoUploaderPreview(fileName, 5, 1);
@@ -154,10 +155,15 @@ public class FileService : IFileService, IDynamicApiController, ITransient
/// 下载.
///
///
+ ///
[HttpGet("down/{fileName}")]
- public async Task FileDown(string fileName)
+ public async Task FileDown(string fileName, [FromQuery] string type)
{
string? systemFilePath = Path.Combine(FileVariable.SystemFilePath, fileName);
+ if (type.IsNotEmptyOrNull())
+ {
+ systemFilePath = Path.Combine(_fileManager.GetPathByType(type), fileName);
+ }
var fileStreamResult = await _fileManager.DownloadFileByType(systemFilePath, fileName);
byte[] bytes = new byte[fileStreamResult.FileStream.Length];
@@ -190,6 +196,39 @@ public class FileService : IFileService, IDynamicApiController, ITransient
return new { name = fileName, url = string.Format("/api/file/Download?encryption={0}", encryptStr) };
}
+ ///
+ /// 全部下载.
+ ///
+ /// 图片类型.
+ /// 文件名称.
+ ///
+ [HttpPost("PackDownload/{type}")]
+ public async Task DownloadAll(string type, [FromBody] List input)
+ {
+ var fileName = RandomExtensions.NextLetterAndNumberString(new Random(), 7);
+ //临时目录
+ string directoryPath = Path.Combine(App.GetConfig("JNPF_App", true).SystemPath, "TemporaryFile", fileName);
+ Directory.CreateDirectory(directoryPath);
+ foreach (var item in input)
+ {
+ string filePath = Path.Combine(GetPathByType(type), item.fileId.Replace("@", "."));
+ await _fileManager.CopyFile(filePath, Path.Combine(directoryPath, item.fileName));
+ }
+ // 压缩文件
+ string downloadPath = directoryPath + ".zip";
+
+ // 判断是否存在同名称文件
+ if (File.Exists(downloadPath))
+ File.Delete(downloadPath);
+
+ ZipFile.CreateFromDirectory(directoryPath, downloadPath);
+ if (!App.Configuration["OSS:Provider"].Equals("Invalid"))
+ await UploadFileByType(downloadPath, "SystemPath", string.Format("文件{0}.zip", fileName));
+ var downloadFileName = string.Format("{0}|{1}.zip|TemporaryFile", _userManager.UserId, fileName);
+ _cacheManager.Set(fileName + ".zip", string.Empty);
+ return new { downloadName = string.Format("文件{0}.zip", fileName), downloadVo = new { name = fileName, url = "/api/File/Download?encryption=" + DESCEncryption.Encrypt(downloadFileName, "JNPF") } };
+ }
+
///
/// 下载文件链接.
///
@@ -268,16 +307,17 @@ public class FileService : IFileService, IDynamicApiController, ITransient
[HttpPost("Uploader/{type}")]
[AllowAnonymous]
[IgnoreLog]
- public async Task Uploader(string type, IFormFile file)
+ public async Task Uploader(string type, [FromForm] ChunkModel input)
{
- string? fileType = Path.GetExtension(file.FileName).Replace(".", string.Empty);
+ string? fileType = Path.GetExtension(input.file.FileName).Replace(".", string.Empty);
if (!AllowFileType(fileType, type))
throw Oops.Oh(ErrorCode.D1800);
- string filePath = GetPathByType(type);
- string fileName = string.Format("{0}{1}{2}", DateTime.Now.ToString("yyyyMMdd"), RandomExtensions.NextLetterAndNumberString(new Random(), 5), Path.GetExtension(file.FileName));
- var stream = file.OpenReadStream();
- await _fileManager.UploadFileByType(stream, filePath, fileName);
- return new { name = fileName, url = string.Format("/api/File/Image/{0}/{1}", type, fileName), fileSize = file.Length, fileExtension = fileType };
+ string saveFileName = string.Format("{0}{1}{2}", DateTime.Now.ToString("yyyyMMdd"), RandomExtensions.NextLetterAndNumberString(new Random(), 5), Path.GetExtension(input.file.FileName));
+ var stream = input.file.OpenReadStream();
+ input.type = type;
+ _fileManager.GetChunkModel(input, saveFileName);
+ await _fileManager.UploadFileByType(stream, input.folder, saveFileName);
+ return new FileControlsModel { name = input.fileName, url = string.Format("/api/File/Image/{0}/{1}", type, input.fileName), fileExtension = fileType, fileSize = input.file.Length, fileName = input.fileName };
}
///
@@ -364,12 +404,18 @@ public class FileService : IFileService, IDynamicApiController, ITransient
/// KKFile 文件预览.
///
/// 文件名称.
+ /// 文件地址.
///
- public string KKFileUploaderPreview(string fileName)
+ public string KKFileUploaderPreview(string fileName, string fileDownloadUrl)
{
var domain = App.Configuration["JNPF_APP:Domain"];
var filePath = (domain + "/api/File/down/" + fileName).ToBase64String();
-
+ if (fileDownloadUrl.IsNotEmptyOrNull())
+ {
+ var list = fileDownloadUrl.Split('/');
+ var type = list.Length > 4 ? list[4] : string.Empty;
+ filePath = string.Format("{0}{1}{2}?type={3}", domain, "/api/File/down/", fileName, type).ToBase64String();
+ }
var kkFileDoMain = App.Configuration["JNPF_APP:KKFileDomain"];
var kkurl = kkFileDoMain + "/onlinePreview?url=";
diff --git a/system/Tnb.Systems/Permission/AuthorizeService.cs b/system/Tnb.Systems/Permission/AuthorizeService.cs
index da29fb93..a680dfc6 100644
--- a/system/Tnb.Systems/Permission/AuthorizeService.cs
+++ b/system/Tnb.Systems/Permission/AuthorizeService.cs
@@ -1,4 +1,5 @@
-using JNPF.Common.Const;
+using Aop.Api.Domain;
+using JNPF.Common.Const;
using JNPF.Common.Core.Handlers;
using JNPF.Common.Core.Manager;
using JNPF.Common.Enums;
@@ -453,7 +454,7 @@ public class AuthorizeService : IAuthorizeService, IDynamicApiController, ITrans
_authorizeRepository.AsSugarClient().Ado.RollbackTran();
}
- if(input.objectId.Any()) await ForcedOffline(input.objectId); // 编辑角色权限退出角色的登录用户
+ if (input.objectId.Any() && !input.itemType.Equals("portal")) await ForcedOffline(input.objectId); // 编辑角色权限退出角色的登录用户
}
///
@@ -1083,7 +1084,7 @@ public class AuthorizeService : IAuthorizeService, IDynamicApiController, ITrans
///
private async Task DelUserInfo(string tenantId, string userId)
{
- var cacheKey = string.Format("{0}{1}_{2}", CommonConst.CACHEKEYUSER, tenantId, userId);
+ var cacheKey = string.Format("{0}:{1}:{2}", tenantId, CommonConst.CACHEKEYUSER, userId);
return await _cacheManager.DelAsync(cacheKey);
}
diff --git a/system/Tnb.Systems/Permission/DepartmentService.cs b/system/Tnb.Systems/Permission/DepartmentService.cs
index 3dc97348..0e74df6e 100644
--- a/system/Tnb.Systems/Permission/DepartmentService.cs
+++ b/system/Tnb.Systems/Permission/DepartmentService.cs
@@ -172,13 +172,16 @@ public class DepartmentService : IDepartmentService, IDynamicApiController, ITra
var pItems = treeList.Select(x => x.organizeIds.FirstOrDefault()).Distinct().ToList();
pItems.ForEach(item =>
{
- var addItem = orgTree.Find(x => x.Id.Equals(item)).Adapt();
- if (addItem.type != null && addItem.type.Equals("company")) addItem.icon = "icon-ym icon-ym-tree-organization3";
- addItem.fullName = orgTree.FirstOrDefault(x => x.Id.Equals(addItem.id))?.Description;
- addItem.organize = addItem.fullName;
- addItem.organizeIds = addItem.organizeIdTree.Split(",").ToList();
- addItem.disabled = true;
- if (!treeList.Any(x => x.id.Equals(addItem.id))) treeList.Add(addItem);
+ if (treeList.Select(x => x.id).Contains(item))
+ {
+ var addItem = orgTree.Find(x => x.Id.Equals(item)).Adapt();
+ if (addItem.type != null && addItem.type.Equals("company")) addItem.icon = "icon-ym icon-ym-tree-organization3";
+ addItem.fullName = orgTree.FirstOrDefault(x => x.Id.Equals(addItem.id))?.Description;
+ addItem.organize = addItem.fullName;
+ addItem.organizeIds = addItem.organizeIdTree.Split(",").ToList();
+ addItem.disabled = true;
+ if (!treeList.Any(x => x.id.Equals(addItem.id))) treeList.Add(addItem);
+ }
});
}
diff --git a/system/Tnb.Systems/Permission/OrganizeAdministratorService.cs b/system/Tnb.Systems/Permission/OrganizeAdministratorService.cs
index e8e913b9..111711c9 100644
--- a/system/Tnb.Systems/Permission/OrganizeAdministratorService.cs
+++ b/system/Tnb.Systems/Permission/OrganizeAdministratorService.cs
@@ -1,4 +1,5 @@
-using JNPF.Common.Core.Manager;
+using JNPF.Common.Contracts;
+using JNPF.Common.Core.Manager;
using JNPF.Common.Enums;
using JNPF.Common.Extension;
using JNPF.Common.Filter;
@@ -86,10 +87,10 @@ public class OrganizeAdministratorService : IOrganizeAdministratorService, IDyna
var userIdList = await _repository.AsSugarClient().Queryable().Where(x => x.ObjectType.Equals("Organize") && orgIds.Contains(x.ObjectId)).Select(x => x.UserId).ToListAsync();
var organizeAdmin = await _repository.AsSugarClient().Queryable().Where(x => !SqlFunc.ToString(x.UserId).Equals(_userManager.UserId))
.WhereIF(!_userManager.IsAdministrator, x => orgIds.Contains(x.OrganizeId) && userIdList.Contains(x.UserId))
- .Select(x => x.UserId).ToListAsync();
+ .Select(x => new { x.UserId, x.CreatorTime }).ToListAsync();
var data = await _repository.AsSugarClient().Queryable()
- .Where(x => organizeAdmin.Contains(x.Id) && x.DeleteMark == null)
+ .Where(x => organizeAdmin.Select(xx => xx.UserId).Contains(x.Id) && x.DeleteMark == null)
.WhereIF(input.keyword.IsNotEmptyOrNull(), x => x.Account.Contains(input.keyword) || x.RealName.Contains(input.keyword))
.Select(x => new OrganizeAdministratorListOutput()
{
@@ -109,6 +110,7 @@ public class OrganizeAdministratorService : IOrganizeAdministratorService, IDyna
// 获取用户组织集合
List? roleOrgList = orgUserIdAll.Where(x => x.UserId == item.id).Select(x => x.ObjectId).ToList();
item.organizeId = string.Join(" , ", orgTreeNameList.Where(x => roleOrgList.Contains(x.Id)).Select(x => x.Description));
+ item.creatorTime = organizeAdmin.Find(x => x.UserId.Equals(item.id)).CreatorTime;
}
return PageResult.SqlSugarPageResult(data);
diff --git a/system/Tnb.Systems/Permission/OrganizeService.cs b/system/Tnb.Systems/Permission/OrganizeService.cs
index 190a515c..fd02a5a2 100644
--- a/system/Tnb.Systems/Permission/OrganizeService.cs
+++ b/system/Tnb.Systems/Permission/OrganizeService.cs
@@ -11,6 +11,7 @@ using JNPF.JsonSerialization;
using JNPF.LinqBuilder;
using JNPF.Systems.Entitys.Dto.Organize;
using JNPF.Systems.Entitys.Dto.SysConfig;
+using JNPF.Systems.Entitys.Dto.User;
using JNPF.Systems.Entitys.Permission;
using JNPF.Systems.Entitys.System;
using JNPF.Systems.Interfaces.Permission;
@@ -215,13 +216,16 @@ public class OrganizeService : IOrganizeService, IDynamicApiController, ITransie
var pItems = treeList.Select(x => x.organizeIds.FirstOrDefault()).Distinct().ToList();
pItems.ForEach(item =>
{
- var addItem = orgTree.Find(x => x.Id.Equals(item)).Adapt();
- if (addItem.type != null && addItem.type.Equals("company")) addItem.icon = "icon-ym icon-ym-tree-organization3";
- addItem.fullName = orgTree.FirstOrDefault(x => x.Id.Equals(addItem.id))?.Description;
- addItem.organize = addItem.fullName;
- addItem.organizeIds = addItem.organizeIdTree.Split(",").ToList();
- addItem.disabled = true;
- if (!treeList.Any(x => x.id.Equals(addItem.id))) treeList.Add(addItem);
+ if (treeList.Select(x => x.id).Contains(item))
+ {
+ var addItem = orgTree.Find(x => x.Id.Equals(item)).Adapt();
+ if (addItem.type != null && addItem.type.Equals("company")) addItem.icon = "icon-ym icon-ym-tree-organization3";
+ addItem.fullName = orgTree.FirstOrDefault(x => x.Id.Equals(addItem.id))?.Description;
+ addItem.organize = addItem.fullName;
+ addItem.organizeIds = addItem.organizeIdTree.Split(",").ToList();
+ addItem.disabled = true;
+ if (!treeList.Any(x => x.id.Equals(addItem.id))) treeList.Add(addItem);
+ }
});
}
@@ -282,6 +286,23 @@ public class OrganizeService : IOrganizeService, IDynamicApiController, ITransie
#region POST
+ ///
+ /// 根据组织Id List 获取当前所属组织(部门).
+ ///
+ ///
+ [HttpPost("getDefaultCurrentValueDepartmentId")]
+ public async Task GetDefaultCurrentValueDepartmentId([FromBody] GetDefaultCurrentValueInput input)
+ {
+ var depId = _repository.AsSugarClient().Queryable().Where(x => x.Id.Equals(_userManager.UserId)).Select(x => x.OrganizeId).First();
+
+ if (input.DepartIds == null || !input.DepartIds.Any()) return new { departmentId = depId };
+ var userRelationList = _repository.AsSugarClient().Queryable().Where(x => input.DepartIds.Contains(x.ObjectId))
+ .Select(x => x.UserId).ToList();
+
+ if (userRelationList.Contains(_userManager.UserId)) return new { userId = depId };
+ else return new { departmentId = string.Empty };
+ }
+
///
/// 通过部门id获取部门列表.
///
@@ -295,19 +316,19 @@ public class OrganizeService : IOrganizeService, IDynamicApiController, ITransie
queryWhere = queryWhere.And(x => x.DeleteMark == null);
List? data = await _repository.AsQueryable().Where(queryWhere)
.WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword)).Select(a => new OrganizeListOutput
- {
- id = a.Id,
- organizeIdTree = a.OrganizeIdTree,
- type = a.Category,
- parentId = a.ParentId,
- lastFullName = a.FullName,
- fullName = a.FullName,
- enabledMark = a.EnabledMark,
- creatorTime = a.CreatorTime,
- icon = a.Category.Equals("company") ? "icon-ym icon-ym-tree-organization3" : "icon-ym icon-ym-tree-department1",
- sortCode = a.SortCode,
- isLeaf = true
- }).ToListAsync();
+ {
+ id = a.Id,
+ organizeIdTree = a.OrganizeIdTree,
+ type = a.Category,
+ parentId = a.ParentId,
+ lastFullName = a.FullName,
+ fullName = a.FullName,
+ enabledMark = a.EnabledMark,
+ creatorTime = a.CreatorTime,
+ icon = a.Category.Equals("company") ? "icon-ym icon-ym-tree-organization3" : "icon-ym icon-ym-tree-department1",
+ sortCode = a.SortCode,
+ isLeaf = true
+ }).ToListAsync();
// 获取所有组织
List? allOrgList = GetOrgListTreeName();
@@ -398,7 +419,7 @@ public class OrganizeService : IOrganizeService, IDynamicApiController, ITransie
});
});
- if (adminlist.Any()) await _repository.AsSugarClient().Insertable(adminlist).CallEntityMethod(m => m.Create()).ExecuteReturnEntityAsync();
+ if(adminlist.Any()) await _repository.AsSugarClient().Insertable(adminlist).CallEntityMethod(m => m.Create()).ExecuteReturnEntityAsync();
#endregion
#region 第三方同步
diff --git a/system/Tnb.Systems/Permission/PositionService.cs b/system/Tnb.Systems/Permission/PositionService.cs
index dd19b31a..9bb961ca 100644
--- a/system/Tnb.Systems/Permission/PositionService.cs
+++ b/system/Tnb.Systems/Permission/PositionService.cs
@@ -124,78 +124,29 @@ public class PositionService : IPositionService, IDynamicApiController, ITransie
childOrgIds.AddRange(_repository.AsSugarClient().Queryable().ToChildList(x => x.ParentId, input.organizeId).Select(x => x.Id).ToList());
childOrgIds = childOrgIds.Distinct().ToList();
}
- var strChildOrgIds = string.Join(",", childOrgIds);
+ var data = await _repository.AsSugarClient().Queryable(
+ (a, b, c) => new JoinQueryInfos(JoinType.Left, b.Id == a.OrganizeId, JoinType.Left, a.Type == c.EnCode && c.DictionaryTypeId == "dae93f2fd7cd4df999d32f8750fa6a1e"))
- SqlSugarPagedList? data = new SqlSugarPagedList();
- if (childOrgIds.Any())
- {
- // 拼接查询
- List>? listQuery = new List>();
- foreach (string item in childOrgIds)
+ // 组织机构
+ .WhereIF(childOrgIds.Any(), a => childOrgIds.Contains(a.OrganizeId))
+ .WhereIF(!_userManager.IsAdministrator, a => dataScope.Contains(a.OrganizeId))
+
+ // 关键字(名称、编码)
+ .WhereIF(!input.keyword.IsNullOrEmpty(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword))
+ .Where(a => a.DeleteMark == null).OrderBy(a => a.SortCode).OrderBy(a => a.CreatorTime, OrderByType.Desc).OrderBy(a => a.LastModifyTime, OrderByType.Desc)
+ .Select((a, b, c) => new PositionListOutput
{
- var quer = _repository.AsQueryable()
-
- // 组织机构
- .Where(a => item.Equals(a.OrganizeId))
- .WhereIF(!_userManager.IsAdministrator, a => dataScope.Contains(a.OrganizeId))
- .WhereIF(!input.keyword.IsNullOrEmpty(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword))
- .Select(a => new PositionListOutput
- {
- id = a.Id,
- fullName = a.FullName,
- enCode = a.EnCode,
- type = SqlFunc.Subqueryable().Where(d => d.EnCode.Equals(a.Type) && d.DictionaryTypeId == "dae93f2fd7cd4df999d32f8750fa6a1e").Select(d => d.FullName),
- department = SqlFunc.Subqueryable().Where(o => o.Id.Equals(a.OrganizeId)).Select(o => o.FullName),
- organizeId = SqlFunc.Subqueryable().Where(o => o.Id.Equals(a.OrganizeId)).Select(o => o.OrganizeIdTree),
- enabledMark = a.EnabledMark,
- creatorTime = a.CreatorTime,
- description = a.Description,
- sortCode = a.SortCode
- });
- listQuery.Add(quer);
- }
-
- data = await _repository.AsSugarClient().UnionAll(listQuery)
- .Select(a => new PositionListOutput
- {
- id = a.id,
- fullName = a.fullName,
- enCode = a.enCode,
- type = a.type,
- department = a.department,
- organizeId = a.organizeId,
- enabledMark = a.enabledMark,
- creatorTime = a.creatorTime,
- description = a.description,
- sortCode = a.sortCode
- }).ToPagedListAsync(input.currentPage, input.pageSize);
- }
- else
- {
- data = await _repository.AsSugarClient().Queryable(
- (a, b, c) => new JoinQueryInfos(JoinType.Left, b.Id == a.OrganizeId, JoinType.Left, a.Type == c.EnCode && c.DictionaryTypeId == "dae93f2fd7cd4df999d32f8750fa6a1e"))
-
- // 组织机构
- .WhereIF(childOrgIds.Any(), a => childOrgIds.Contains(a.OrganizeId))
- .WhereIF(!_userManager.IsAdministrator, a => dataScope.Contains(a.OrganizeId))
-
- // 关键字(名称、编码)
- .WhereIF(!input.keyword.IsNullOrEmpty(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword))
- .Where(a => a.DeleteMark == null).OrderBy(a => a.SortCode).OrderBy(a => a.CreatorTime, OrderByType.Desc).OrderBy(a => a.LastModifyTime, OrderByType.Desc)
- .Select((a, b, c) => new PositionListOutput
- {
- id = a.Id,
- fullName = a.FullName,
- enCode = a.EnCode,
- type = c.FullName,
- department = b.FullName,
- organizeId = b.OrganizeIdTree,
- enabledMark = a.EnabledMark,
- creatorTime = a.CreatorTime,
- description = a.Description,
- sortCode = a.SortCode
- }).ToPagedListAsync(input.currentPage, input.pageSize);
- }
+ id = a.Id,
+ fullName = a.FullName,
+ enCode = a.EnCode,
+ type = c.FullName,
+ department = b.FullName,
+ organizeId = b.OrganizeIdTree,
+ enabledMark = a.EnabledMark,
+ creatorTime = a.CreatorTime,
+ description = a.Description,
+ sortCode = a.SortCode
+ }).ToPagedListAsync(input.currentPage, input.pageSize);
// 处理组织树 名称
List? orgList = _organizeService.GetOrgListTreeName();
diff --git a/system/Tnb.Systems/Permission/RoleService.cs b/system/Tnb.Systems/Permission/RoleService.cs
index bbac5217..65dcd4de 100644
--- a/system/Tnb.Systems/Permission/RoleService.cs
+++ b/system/Tnb.Systems/Permission/RoleService.cs
@@ -102,62 +102,42 @@ public class RoleService : IRoleService, IDynamicApiController, ITransient
SqlSugarPagedList? data = new SqlSugarPagedList();
if (childOrgIds.Any())
{
- // 拼接查询
- List>? listQuery = new List>();
- foreach (string item in childOrgIds)
- {
- var quer = _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == a.ObjectId))
- .Where((a, b) => item == a.OrganizeId)
- .WhereIF(!pageInput.keyword.IsNullOrEmpty(), (a, b) => b.FullName.Contains(pageInput.keyword) || b.EnCode.Contains(pageInput.keyword))
- .WhereIF(!_userManager.IsAdministrator, a => dataScope.Contains(a.ObjectId))
- .Where((a, b) => b.DeleteMark == null)
+ data = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, a.Id == b.ObjectId))
+ .Where((a, b) => childOrgIds.Contains(b.OrganizeId)).Where((a, b) => a.DeleteMark == null)
+ .WhereIF(!pageInput.keyword.IsNullOrEmpty(), (a, b) => a.FullName.Contains(pageInput.keyword) || a.EnCode.Contains(pageInput.keyword))
+ .WhereIF(!_userManager.IsAdministrator, (a, b) => dataScope.Contains(b.OrganizeId))
+ .GroupBy((a, b) => new { a.Id, a.Type, a.GlobalMark, a.EnCode, a.FullName, a.EnabledMark, a.CreatorTime, a.SortCode })
.Select((a, b) => new RoleListOutput
{
- id = b.Id,
- parentId = b.Type,
- type = SqlFunc.IIF(b.GlobalMark == 1, "全局", "组织"),
- enCode = b.EnCode,
- fullName = b.FullName,
- enabledMark = b.EnabledMark,
- creatorTime = b.CreatorTime,
- sortCode = b.SortCode
- });
- listQuery.Add(quer);
- }
- var sql = _repository.AsSugarClient().UnionAll(listQuery).Where(a => !SqlFunc.IsNullOrEmpty(a.id)).ToSqlString();
- data = await _repository.AsSugarClient().UnionAll(listQuery).Where(a => !SqlFunc.IsNullOrEmpty(a.id))
- .GroupBy(a => new { a.id, a.parentId, a.type, a.creatorTime, a.enCode, a.fullName, a.sortCode, a.enabledMark })
- .Select(a => new RoleListOutput
- {
- id = a.id,
- parentId = a.parentId,
- type = a.type,
- creatorTime = a.creatorTime,
- enCode = a.enCode,
- fullName = a.fullName,
- sortCode = a.sortCode
- }).ToPagedListAsync(input.currentPage, input.pageSize);
+ id = a.Id,
+ parentId = a.Type,
+ type = SqlFunc.IIF(a.GlobalMark == 1, "全局", "组织"),
+ enCode = a.EnCode,
+ fullName = a.FullName,
+ enabledMark = a.EnabledMark,
+ creatorTime = a.CreatorTime,
+ sortCode = a.SortCode
+ }).MergeTable().OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize);
}
else
{
- data = await _repository.AsSugarClient().Queryable()
- .WhereIF(input.organizeId == "0", a => a.GlobalMark == 1)
- .WhereIF(!_userManager.IsAdministrator, a => a.GlobalMark == 0)
- .WhereIF(!_userManager.IsAdministrator, a => a.GlobalMark == 1)
- .WhereIF(!string.IsNullOrEmpty(input.keyword), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword))
- .Where(a => a.DeleteMark == null)
- .Select((a) => new RoleListOutput
- {
- id = a.Id,
- parentId = a.Type,
- type = SqlFunc.IIF(a.GlobalMark == 1, "全局", "组织"),
- enCode = a.EnCode,
- fullName = a.FullName,
- description = a.Description,
- enabledMark = a.EnabledMark,
- creatorTime = a.CreatorTime,
- sortCode = a.SortCode
- }).MergeTable().OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize);
+ data = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, a.Id == b.ObjectId))
+ .Where((a, b) => a.DeleteMark == null)
+ .WhereIF(input.organizeId == "0", (a, b) => a.GlobalMark == 1)
+ .WhereIF(!pageInput.keyword.IsNullOrEmpty(), (a, b) => a.FullName.Contains(pageInput.keyword) || a.EnCode.Contains(pageInput.keyword))
+ .WhereIF(!_userManager.IsAdministrator && input.organizeId != "0", (a, b) => dataScope.Contains(b.OrganizeId))
+ .GroupBy((a, b) => new { a.Id, a.Type, a.GlobalMark, a.EnCode, a.FullName, a.EnabledMark, a.CreatorTime, a.SortCode })
+ .Select((a, b) => new RoleListOutput
+ {
+ id = a.Id,
+ parentId = a.Type,
+ type = SqlFunc.IIF(a.GlobalMark == 1, "全局", "组织"),
+ enCode = a.EnCode,
+ fullName = a.FullName,
+ enabledMark = a.EnabledMark,
+ creatorTime = a.CreatorTime,
+ sortCode = a.SortCode
+ }).MergeTable().OrderBy(a => a.sortCode).OrderBy(a => a.creatorTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize);
}
#region 处理 多组织
@@ -169,11 +149,8 @@ public class RoleService : IRoleService, IDynamicApiController, ITransient
// 获取组织集合
var organizeList = orgUserIdAll.Where(x => x.ObjectId == item.id).Select(x => x.OrganizeId).ToList();
item.organizeInfo = string.Join(" ; ", orgTreeNameList.Where(x => organizeList.Contains(x.Id)).Select(x => x.Description));
- item.sortCode = 999;
- if (organizeList.Contains(input.organizeId)) item.sortCode = 0;
}
- data.list = data.list.OrderBy(x => x.sortCode).ToList();
#endregion
return PageResult.SqlSugarPageResult(data);
diff --git a/system/Tnb.Systems/Permission/SocialsUserService.cs b/system/Tnb.Systems/Permission/SocialsUserService.cs
index 5241c19c..2c0df364 100644
--- a/system/Tnb.Systems/Permission/SocialsUserService.cs
+++ b/system/Tnb.Systems/Permission/SocialsUserService.cs
@@ -354,7 +354,7 @@ public class SocialsUserService : ISocialsUserService, IDynamicApiController, IT
return new WeChatOpenAuthRequest(clientConfig, authStateCache);
case DefaultAuthSourceEnum.WECHAT_ENTERPRISE:
- //return new WeChatEnterpriseAuthRequest(clientConfig, authStateCache);
+ //return new WeChatEnterpriseAuthRequest(clientConfig, authStateCache);
case DefaultAuthSourceEnum.WECHAT_ENTERPRISE_SCAN:
clientConfig.redirectUri = HttpUtility.UrlEncode(clientConfig.redirectUri);
@@ -554,4 +554,5 @@ public class SocialsUserService : ISocialsUserService, IDynamicApiController, IT
var socialName = resData.username.IsNullOrWhiteSpace() ? resData.nickname : resData.username;
return await GetUserInfo(model.source, uuid, socialName);
}
+
}
\ No newline at end of file
diff --git a/system/Tnb.Systems/Permission/UsersCurrentService.cs b/system/Tnb.Systems/Permission/UsersCurrentService.cs
index 6caad7e8..09535467 100644
--- a/system/Tnb.Systems/Permission/UsersCurrentService.cs
+++ b/system/Tnb.Systems/Permission/UsersCurrentService.cs
@@ -17,6 +17,7 @@ using JNPF.Systems.Entitys.Model.UsersCurrent;
using JNPF.Systems.Entitys.Permission;
using JNPF.Systems.Entitys.System;
using JNPF.Systems.Interfaces.Permission;
+using JNPF.Systems.Interfaces.System;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
@@ -50,11 +51,21 @@ public class UsersCurrentService : IUsersCurrentService, IDynamicApiController,
///
private readonly ICacheManager _cacheManager;
+ ///
+ /// 系统配置.
+ ///
+ private readonly ISysConfigService _sysConfigService;
+
///
/// 用户管理.
///
private readonly IUserManager _userManager;
+ ///
+ /// 操作权限服务.
+ ///
+ private readonly OnlineUserService _onlineUserService;
+
///
/// 初始化一个类型的新实例.
///
@@ -63,12 +74,16 @@ public class UsersCurrentService : IUsersCurrentService, IDynamicApiController,
IAuthorizeService authorizeService,
IOrganizeService organizeService,
ICacheManager cacheManager,
+ ISysConfigService sysConfigService,
+ OnlineUserService onlineUserService,
IUserManager userManager)
{
_repository = userRepository;
_authorizeService = authorizeService;
_organizeService = organizeService;
_cacheManager = cacheManager;
+ _sysConfigService = sysConfigService;
+ _onlineUserService = onlineUserService;
_userManager = userManager;
}
@@ -126,7 +141,7 @@ public class UsersCurrentService : IUsersCurrentService, IDynamicApiController,
position = string.Empty,
positionId = a.PositionId,
organizeId = a.OrganizeId,
- manager = SqlFunc.Subqueryable().Where(x => x.Id.Equals(a.Id)).Select(x => SqlFunc.MergeString(x.RealName, "/", x.Account)),
+ manager = SqlFunc.Subqueryable().Where(x => x.Id.Equals(a.ManagerId)).Select(x => SqlFunc.MergeString(x.RealName, "/", x.Account)),
roleId = string.Empty,
roleIds = a.RoleId,
creatorTime = a.CreatorTime,
@@ -305,6 +320,7 @@ public class UsersCurrentService : IUsersCurrentService, IDynamicApiController,
if (MD5Encryption.Encrypt(input.oldPassword + user.Secretkey) != user.Password.ToLower())
throw Oops.Oh(ErrorCode.D5007);
string? imageCode = await GetCode(input.timestamp);
+ await PwdStrategy(input);
if (!input.code.ToLower().Equals(imageCode.ToLower()))
{
throw Oops.Oh(ErrorCode.D5015);
@@ -312,15 +328,14 @@ public class UsersCurrentService : IUsersCurrentService, IDynamicApiController,
else
{
await DelCode(input.timestamp);
- await DelUserInfo(string.Format("{0}_{1}", _userManager.TenantId, user.Id));
+ await DelUserInfo(_userManager.TenantId, user.Id);
+ await _onlineUserService.ForcedOffline(user.Id);
}
-
user.Password = MD5Encryption.Encrypt(input.password + user.Secretkey);
user.ChangePasswordDate = DateTime.Now;
user.LastModifyTime = DateTime.Now;
user.LastModifyUserId = _userManager.UserId;
- int isOk = await _repository.AsUpdateable(user).UpdateColumns(it => new
- {
+ int isOk = await _repository.AsUpdateable(user).UpdateColumns(it => new {
it.Password,
it.ChangePasswordDate,
it.LastModifyUserId,
@@ -341,8 +356,7 @@ public class UsersCurrentService : IUsersCurrentService, IDynamicApiController,
userInfo.IsAdministrator = Convert.ToInt32(_userManager.IsAdministrator);
userInfo.LastModifyTime = DateTime.Now;
userInfo.LastModifyUserId = _userManager.UserId;
- int isOk = await _repository.AsUpdateable(userInfo).UpdateColumns(it => new
- {
+ int isOk = await _repository.AsUpdateable(userInfo).UpdateColumns(it => new {
it.RealName,
it.Signature,
it.Gender,
@@ -376,8 +390,7 @@ public class UsersCurrentService : IUsersCurrentService, IDynamicApiController,
user.Theme = input.theme;
user.LastModifyTime = DateTime.Now;
user.LastModifyUserId = _userManager.UserId;
- int isOk = await _repository.AsUpdateable(user).UpdateColumns(it => new
- {
+ int isOk = await _repository.AsUpdateable(user).UpdateColumns(it => new {
it.Theme,
it.LastModifyUserId,
it.LastModifyTime
@@ -396,8 +409,7 @@ public class UsersCurrentService : IUsersCurrentService, IDynamicApiController,
user.Language = input.language;
user.LastModifyTime = DateTime.Now;
user.LastModifyUserId = _userManager.UserId;
- int isOk = await _repository.AsUpdateable(user).UpdateColumns(it => new
- {
+ int isOk = await _repository.AsUpdateable(user).UpdateColumns(it => new {
it.Language,
it.LastModifyUserId,
it.LastModifyTime
@@ -416,8 +428,7 @@ public class UsersCurrentService : IUsersCurrentService, IDynamicApiController,
user.HeadIcon = name;
user.LastModifyTime = DateTime.Now;
user.LastModifyUserId = _userManager.UserId;
- int isOk = await _repository.AsUpdateable(user).UpdateColumns(it => new
- {
+ int isOk = await _repository.AsUpdateable(user).UpdateColumns(it => new {
it.HeadIcon,
it.LastModifyUserId,
it.LastModifyTime
@@ -468,8 +479,17 @@ public class UsersCurrentService : IUsersCurrentService, IDynamicApiController,
if (input.menuType.Equals(1))
{
// 系统下没有菜单不允许切换.
- if (!await _repository.AsSugarClient().Queryable().AnyAsync(x => x.SystemId.Equals(input.majorId) && x.DeleteMark == null && x.Category.Equals("App")))
- throw Oops.Oh(ErrorCode.D4009);
+ var mList = await _repository.AsSugarClient().Queryable().Where(x => x.SystemId.Equals(input.majorId) && x.DeleteMark == null && x.Category.Equals("App")).Select(x => x.Id).ToListAsync();
+ if (!mList.Any()) throw Oops.Oh(ErrorCode.D4009);
+
+ List? roleList = await _userManager.GetUserOrgRoleIds(userInfo.RoleId, userInfo.OrganizeId);
+
+ // 非管理员 没有任何权限 切换失败
+ if (!_userManager.IsAdministrator && !_repository.AsSugarClient().Queryable()
+ .Where(x => x.ObjectType == "Role" && x.ItemType == "module" && roleList.Contains(x.ObjectId))
+ .Where(x => mList.Contains(x.ItemId)).Any())
+ throw Oops.Oh(ErrorCode.D5023);
+
userInfo.SystemId = input.majorId;
}
else
@@ -501,8 +521,7 @@ public class UsersCurrentService : IUsersCurrentService, IDynamicApiController,
userInfo.LastModifyTime = DateTime.Now;
userInfo.LastModifyUserId = _userManager.UserId;
- int isOk = await _repository.AsUpdateable(userInfo).UpdateColumns(it => new
- {
+ int isOk = await _repository.AsUpdateable(userInfo).UpdateColumns(it => new {
it.OrganizeId,
it.PositionId,
it.LastModifyUserId,
@@ -709,14 +728,48 @@ public class UsersCurrentService : IUsersCurrentService, IDynamicApiController,
///
/// 删除用户登录信息缓存.
///
+ /// 租户ID.
/// 用户ID.
///
- private Task DelUserInfo(string userId)
+ private Task DelUserInfo(string tenantId, string userId)
{
- string? cacheKey = string.Format("{0}{1}", CommonConst.CACHEKEYUSER, userId);
+ string? cacheKey = string.Format("{0}:{1}:{2}", tenantId, CommonConst.CACHEKEYUSER, userId);
_cacheManager.DelAsync(cacheKey);
return Task.FromResult(true);
}
+ ///
+ /// 密码策略验证.
+ ///
+ ///
+ private async Task PwdStrategy(UsersCurrentActionsModifyPasswordInput input)
+ {
+ // 系统配置信息
+ var sysInfo = await _sysConfigService.GetInfo();
+ // 禁用旧密码
+ if (sysInfo.disableOldPassword == 1 && sysInfo.disableTheNumberOfOldPasswords > 0)
+ {
+ var oldPwdList = _repository.AsSugarClient().Queryable().Where(x => x.UserId == _userManager.UserId).OrderByDescending(o => o.CreatorTime).Take(sysInfo.disableTheNumberOfOldPasswords).ToList();
+ if (oldPwdList.Any())
+ {
+ foreach (var item in oldPwdList)
+ {
+ if (MD5Encryption.Encrypt(input.password + item.Secretkey) == item.OldPassword.ToLower())
+ throw Oops.Oh(ErrorCode.D5026);
+ }
+ }
+ }
+
+ // 保存旧密码数据
+ var oldPwdEntity = new UserOldPasswordEntity();
+ oldPwdEntity.Id = SnowflakeIdHelper.NextId();
+ oldPwdEntity.UserId = _userManager.UserId;
+ oldPwdEntity.Account = _userManager.Account;
+ oldPwdEntity.OldPassword = MD5Encryption.Encrypt(input.password + _userManager.User.Secretkey);
+ oldPwdEntity.Secretkey = _userManager.User.Secretkey;
+ oldPwdEntity.CreatorTime = DateTime.Now;
+ oldPwdEntity.TenantId = _userManager.TenantId;
+ _repository.AsSugarClient().Insertable(oldPwdEntity).ExecuteCommand();
+ }
#endregion
}
\ No newline at end of file
diff --git a/system/Tnb.Systems/Permission/UsersService.cs b/system/Tnb.Systems/Permission/UsersService.cs
index d355ef61..18cf74b8 100644
--- a/system/Tnb.Systems/Permission/UsersService.cs
+++ b/system/Tnb.Systems/Permission/UsersService.cs
@@ -1,7 +1,9 @@
-using JNPF.Common.Configuration;
+using Aop.Api.Domain;
+using JNPF.Common.Configuration;
using JNPF.Common.Const;
using JNPF.Common.Core.Manager;
using JNPF.Common.Core.Manager.Files;
+using JNPF.Common.Dtos.OAuth;
using JNPF.Common.Enums;
using JNPF.Common.Extension;
using JNPF.Common.Filter;
@@ -9,27 +11,42 @@ using JNPF.Common.Helper;
using JNPF.Common.Manager;
using JNPF.Common.Models.NPOI;
using JNPF.Common.Models.User;
+using JNPF.Common.Options;
using JNPF.Common.Security;
using JNPF.DatabaseAccessor;
using JNPF.DataEncryption;
using JNPF.DependencyInjection;
using JNPF.DynamicApiController;
+using JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
using JNPF.FriendlyException;
+using JNPF.RemoteRequest.Extensions;
using JNPF.Systems.Entitys.Dto.Organize;
using JNPF.Systems.Entitys.Dto.Role;
using JNPF.Systems.Entitys.Dto.SysConfig;
using JNPF.Systems.Entitys.Dto.User;
using JNPF.Systems.Entitys.Dto.UserRelation;
using JNPF.Systems.Entitys.Enum;
+using JNPF.Systems.Entitys.Model.Permission.User;
using JNPF.Systems.Entitys.Permission;
using JNPF.Systems.Entitys.System;
using JNPF.Systems.Interfaces.Permission;
using JNPF.Systems.Interfaces.System;
using Mapster;
+using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.CodeAnalysis;
+using Microsoft.Extensions.Options;
+using NPOI.SS.Formula.Eval;
+using NPOI.SS.Formula.Functions;
+using Org.BouncyCastle.Ocsp;
+using Qiniu.Util;
+using Senparc.NeuChar.App.AppStore;
using SqlSugar;
+using System;
using System.Linq.Expressions;
+using System.Security.Principal;
+using System.Text.Json.Nodes;
namespace JNPF.Systems;
@@ -40,6 +57,11 @@ namespace JNPF.Systems;
[Route("api/permission/[controller]")]
public class UsersService : IUsersService, IDynamicApiController, ITransient
{
+ ///
+ /// 配置文档.
+ ///
+ private readonly OauthOptions _oauthOptions = App.GetConfig("OAuth", true);
+
///
/// 服务基础仓储.
///
@@ -80,6 +102,16 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
///
private readonly IUserManager _userManager;
+ ///
+ /// SqlSugarClient客户端.
+ ///
+ private SqlSugarScope _sqlSugarClient;
+
+ ///
+ /// 多租户配置选项.
+ ///
+ private readonly TenantOptions _tenant;
+
///
/// 初始化一个类型的新实例.
///
@@ -91,6 +123,8 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
ISynThirdInfoService synThirdInfoService,
ICacheManager cacheManager,
IFileManager fileService,
+ ISqlSugarClient sqlSugarClient,
+ IOptions tenantOptions,
IUserManager userManager)
{
_repository = userRepository;
@@ -101,6 +135,8 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
_cacheManager = cacheManager;
_synThirdInfoService = synThirdInfoService;
_fileManager = fileService;
+ _tenant = tenantOptions.Value;
+ _sqlSugarClient = (SqlSugarScope)sqlSugarClient;
}
#region GET
@@ -140,70 +176,26 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
ErrorStrategy configLockType = (ErrorStrategy)Enum.Parse(typeof(ErrorStrategy), config?.Value);
SqlSugarPagedList? data = new SqlSugarPagedList();
- if (childOrgIds.Any())
- {
- // 拼接查询
- List>? listQuery = new List>();
- foreach (string item in childOrgIds)
- {
- var quer = _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == a.UserId))
- .Where((a, b) => item == a.ObjectId)
- .WhereIF(!pageInput.keyword.IsNullOrEmpty(), (a, b) => b.Account.Contains(pageInput.keyword) || b.RealName.Contains(pageInput.keyword))
- .WhereIF(!_userManager.IsAdministrator, a => dataScope.Contains(a.ObjectId))
- .Where((a, b) => b.DeleteMark == null && !b.Id.Equals("admin"))
- .Select((a, b) => new UserListOutput
- {
- id = b.Id,
- account = b.Account,
- realName = b.RealName,
- headIcon = b.HeadIcon,
- creatorTime = b.CreatorTime,
- gender = b.Gender,
- mobilePhone = b.MobilePhone,
- sortCode = b.SortCode,
- unLockTime = b.UnLockTime,
- enabledMark = b.EnabledMark
- });
- listQuery.Add(quer);
- }
- data = await _repository.AsSugarClient().UnionAll(listQuery)
- .GroupBy(a => new { a.id, a.account, a.realName, a.creatorTime, a.gender, a.mobilePhone, a.sortCode, a.enabledMark, a.unLockTime })
- .Select(a => new UserListOutput
- {
- id = a.id,
- account = a.account,
- realName = a.realName,
- creatorTime = a.creatorTime,
- gender = a.gender,
- mobilePhone = a.mobilePhone,
- sortCode = a.sortCode,
- enabledMark = SqlFunc.IIF(configLockType == ErrorStrategy.Delay && a.enabledMark == 2 && a.unLockTime < DateTime.Now, 1, a.enabledMark)
- }).ToPagedListAsync(input.currentPage, input.pageSize);
- var userHeadIcon = await _repository.AsQueryable().Where(x => data.list.Select(xx => xx.id).Contains(x.Id)).Select(x => new { Id = x.Id, headIcon = x.HeadIcon }).ToListAsync();
- foreach (var item in data.list) item.headIcon = "/api/File/Image/userAvatar/" + userHeadIcon.Find(x => x.Id.Equals(item.id)).headIcon;
- }
- else
- {
- data = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == a.UserId))
- .Where((a, b) => b.DeleteMark == null && !b.Id.Equals("admin"))
- .WhereIF(!pageInput.keyword.IsNullOrEmpty(), (a, b) => b.Account.Contains(pageInput.keyword) || b.RealName.Contains(pageInput.keyword))
- .WhereIF(!_userManager.IsAdministrator, (a, b) => dataScope.Contains(a.ObjectId))
- .OrderBy((a, b) => b.SortCode).OrderBy((a, b) => b.CreatorTime, OrderByType.Desc).OrderBy((a, b) => b.LastModifyTime, OrderByType.Desc)
- .GroupBy((a, b) => new { b.Id, b.Account, b.RealName, b.CreatorTime, b.LastModifyTime, b.Gender, b.MobilePhone, b.SortCode, b.EnabledMark, b.UnLockTime })
- .Select((a, b) => new UserListOutput
- {
- id = b.Id,
- account = b.Account,
- realName = b.RealName,
- headIcon = SqlFunc.Subqueryable().Where(e => e.Id == b.Id).Select(u => SqlFunc.MergeString("/api/File/Image/userAvatar/", u.HeadIcon)),
- creatorTime = b.CreatorTime,
- gender = b.Gender,
- mobilePhone = b.MobilePhone,
- sortCode = b.SortCode,
- enabledMark = SqlFunc.IIF(configLockType == ErrorStrategy.Delay && b.EnabledMark == 2 && b.UnLockTime < DateTime.Now, 1, b.EnabledMark)
- }).ToPagedListAsync(input.currentPage, input.pageSize);
- }
+ data = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == a.UserId))
+ .Where((a, b) => b.DeleteMark == null && !b.Account.Equals("admin"))
+ .WhereIF(childOrgIds.Any(), (a, b) => childOrgIds.Contains(a.ObjectId))
+ .WhereIF(!pageInput.keyword.IsNullOrEmpty(), (a, b) => b.Account.Contains(pageInput.keyword) || b.RealName.Contains(pageInput.keyword))
+ .WhereIF(!_userManager.IsAdministrator, (a, b) => dataScope.Contains(a.ObjectId))
+ .OrderBy((a, b) => b.SortCode).OrderBy((a, b) => b.CreatorTime, OrderByType.Desc).OrderBy((a, b) => b.LastModifyTime, OrderByType.Desc)
+ .GroupBy((a, b) => new { b.Id, b.Account, b.RealName, b.CreatorTime, b.LastModifyTime, b.Gender, b.MobilePhone, b.SortCode, b.EnabledMark, b.UnLockTime })
+ .Select((a, b) => new UserListOutput
+ {
+ id = b.Id,
+ account = b.Account,
+ realName = b.RealName,
+ headIcon = SqlFunc.Subqueryable().Where(e => e.Id == b.Id).Select(u => SqlFunc.MergeString("/api/File/Image/userAvatar/", u.HeadIcon)),
+ creatorTime = b.CreatorTime,
+ gender = b.Gender,
+ mobilePhone = b.MobilePhone,
+ sortCode = b.SortCode,
+ enabledMark = SqlFunc.IIF(configLockType == ErrorStrategy.Delay && b.EnabledMark == 2 && b.UnLockTime < DateTime.Now, 1, b.EnabledMark)
+ }).ToPagedListAsync(input.currentPage, input.pageSize);
#region 处理 用户 多组织
@@ -214,11 +206,8 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
// 获取用户组织集合
item.organizeList = orgUserIdAll.Where(x => x.UserId == item.id).Select(x => x.ObjectId).ToList();
item.organize = string.Join(" ; ", orgTreeNameList.Where(x => item.organizeList.Contains(x.Id)).Select(x => x.Description));
- item.sortCode = 999;
- if (item.organizeList.Contains(input.organizeId)) item.sortCode = 0;
}
- data.list = data.list.OrderBy(x => x.sortCode).ToList();
#endregion
return PageResult.SqlSugarPageResult(data);
@@ -323,8 +312,7 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
.Where((a, b) => b.ObjectType == "Organize" && orgList.Contains(b.ObjectId)).Where((a, b) => a.EnabledMark == 1 && a.DeleteMark == null)
.Where((a, b) => a.RealName.Contains(input.keyword) || a.Account.Contains(input.keyword))
.GroupBy((a, b) => new { a.Id, a.RealName, a.Account, a.EnabledMark })
- .Select((a, b) => new
- {
+ .Select((a, b) => new {
id = a.Id,
fullName = SqlFunc.MergeString(a.RealName, "/", a.Account),
enabledMark = a.EnabledMark,
@@ -369,8 +357,7 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
var res = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.UserId == a.Id))
.Where((a, b) => b.ObjectType == "Organize" && b.ObjectId == input.organizeId).Where((a, b) => a.EnabledMark == 1 && a.DeleteMark == null)
.GroupBy((a, b) => new { a.Id, a.RealName, a.Account, a.EnabledMark })
- .Select((a, b) => new
- {
+ .Select((a, b) => new {
id = a.Id,
fullName = SqlFunc.MergeString(a.RealName, "/", a.Account),
enabledMark = a.EnabledMark,
@@ -527,6 +514,24 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
#region POST
+ ///
+ /// 根据用户Id List 获取当前用户Id.
+ ///
+ ///
+ [HttpPost("getDefaultCurrentValueUserId")]
+ public async Task GetDefaultCurrentValueUserId([FromBody] GetDefaultCurrentValueInput input)
+ {
+ if ((input.UserIds == null || !input.UserIds.Any()) && (input.DepartIds == null || !input.DepartIds.Any()) && (input.PositionIds == null || !input.PositionIds.Any())
+ && (input.RoleIds == null || !input.RoleIds.Any()) && (input.GroupIds == null || !input.GroupIds.Any())) return new { userId = _userManager.UserId };
+
+ var userRelationList = _repository.AsSugarClient().Queryable().Select(x => new UserRelationEntity() { UserId = x.UserId, ObjectId = x.ObjectId }).ToList();
+ var userIdList = userRelationList.Where(x => input.UserIds.Contains(x.UserId) || input.DepartIds.Contains(x.ObjectId)
+ || input.PositionIds.Contains(x.ObjectId) || input.RoleIds.Contains(x.ObjectId) || input.GroupIds.Contains(x.ObjectId)).Select(x => x.UserId).ToList();
+
+ if (userIdList.Contains(_userManager.UserId)) return new { userId = _userManager.UserId };
+ else return new { userId = string.Empty };
+ }
+
///
/// 获取.
///
@@ -534,16 +539,14 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
[HttpPost("GetUserList")]
public async Task GetUserList([FromBody] UserRelationInput input)
{
- var data = await _repository.AsSugarClient().Queryable((u, org) => new JoinQueryInfos(JoinType.Inner, u.OrganizeId == org.Id))
- .Where((u, org) => u.EnabledMark > 0 && u.DeleteMark == null)
- .Where((u, org) => input.userId.Contains(u.Id))
- .Select((u, org) => new OrganizeMemberListOutput()
+ var data = await _repository.AsQueryable().Where(it => it.EnabledMark > 0 && it.DeleteMark == null)
+ .Where(it => input.userId.Contains(it.Id))
+ .Select(it => new OrganizeMemberListOutput()
{
- id = u.Id,
- fullName = SqlFunc.MergeString(u.RealName, "/", u.Account),
- headIcon = SqlFunc.MergeString("/api/File/Image/userAvatar/", u.HeadIcon),
- enabledMark = u.EnabledMark,
- type = org.FullName,
+ id = it.Id,
+ fullName = SqlFunc.MergeString(it.RealName, "/", it.Account),
+ headIcon = SqlFunc.MergeString("/api/File/Image/userAvatar/", it.HeadIcon),
+ enabledMark = it.EnabledMark,
}).ToListAsync();
data = data.OrderBy(x => input.userId.IndexOf(x.id)).ToList();
@@ -561,6 +564,7 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
var oids = userList.Where(x => x.UserId.Equals(item.id)).Select(x => x.ObjectId).ToList();
var oTree = orgList.Where(x => oids.Contains(x.Id)).Select(x => x.Description).ToList();
item.organize = string.Join(",", oTree);
+ //item.type = org.fullName;
});
}
@@ -804,15 +808,12 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
if (input.roleIds != null) input.departIds.AddRange(input.roleIds);
if (input.groupIds != null) input.departIds.AddRange(input.groupIds);
if (!input.departIds.Any()) return PageResult.SqlSugarPageResult(data);
- data = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == a.UserId))
+ var ids = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == a.UserId))
.Where((a, b) => b.DeleteMark == null)
.WhereIF(input.departIds.Any() || input.userIds.Any(), (a, b) => input.departIds.Contains(a.ObjectId) || input.userIds.Contains(b.Id))
.WhereIF(input.pagination.keyword.IsNotEmptyOrNull(), (a, b) => b.Account.Contains(input.pagination.keyword) || b.RealName.Contains(input.pagination.keyword))
- .Select((a, b) => new UserListOutput()
- {
- id = b.Id
- }).Distinct().ToPagedListAsync(input.pagination.currentPage, input.pagination.pageSize);
- data = await _repository.AsQueryable().Where(x => data.list.Select(xx => xx.id).Contains(x.Id)).Select(x => new UserListOutput()
+ .Select((a, b) => b.Id).Distinct().ToListAsync();
+ data = await _repository.AsQueryable().Where(x => ids.Contains(x.Id)).Select(x => new UserListOutput()
{
id = x.Id,
organizeId = x.OrganizeId,
@@ -821,8 +822,7 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
headIcon = SqlFunc.MergeString("/api/File/Image/userAvatar/", x.HeadIcon),
gender = x.Gender,
mobilePhone = x.MobilePhone
- }).ToPagedListAsync(1, input.pagination.pageSize);
-
+ }).ToPagedListAsync(input.pagination.currentPage, input.pagination.pageSize);
if (data.list.Any())
{
var orgList = _organizeService.GetOrgListTreeName();
@@ -1075,6 +1075,9 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
}
#endregion
+
+ // 单点登录同步
+ await syncUserInfo(entity, "create", _userManager.TenantId);
}
catch (Exception)
{
@@ -1130,6 +1133,9 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
}
#endregion
+
+ // 单点登录同步
+ await syncUserInfo(entity, "delete", _userManager.TenantId);
}
///
@@ -1142,6 +1148,7 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
public async Task Update(string id, [FromBody] UserUpInput input)
{
UserEntity? oldUserEntity = await _repository.GetFirstAsync(it => it.Id == id);
+ input.roleId = input.roleId == null ? string.Empty : input.roleId;
// 超级管理员 只有 admin 账号才有变更权限
if (_userManager.UserId != oldUserEntity.Id && oldUserEntity.IsAdministrator == 1 && _userManager.Account != "admin")
@@ -1233,8 +1240,7 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
try
{
// 更新用户记录
- int newEntity = await _repository.AsUpdateable(entity).UpdateColumns(it => new
- {
+ int newEntity = await _repository.AsUpdateable(entity).UpdateColumns(it => new {
it.Account,
it.RealName,
it.QuickQuery,
@@ -1315,6 +1321,9 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
}
#endregion
+
+ // 单点登录同步
+ await syncUserInfo(entity, "update", _userManager.TenantId);
}
///
@@ -1372,7 +1381,9 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
if (!(isOk > 0)) throw Oops.Oh(ErrorCode.D5005);
- // 强制将用户提掉线
+ // 单点登录同步
+ entity.Password = input.userPassword;
+ await syncUserInfo(entity, "modifyPassword", _userManager.TenantId);
}
///
@@ -1794,6 +1805,8 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
#endregion
+ #region PrivateMethod
+
///
/// 获取集合中的组织 树,根据上级ID.
///
@@ -2256,5 +2269,244 @@ public class UsersService : IUsersService, IDynamicApiController, ITransient
return output;
}
+ #endregion
+ #region 单点登录 数据同步
+
+ ///
+ /// 同步数据导maxkey.
+ ///
+ ///
+ ///
+ ///
+ public async Task syncUserInfo(UserEntity userEntity, string method, string tenantId)
+ {
+ try
+ {
+ if (_oauthOptions.Enabled)
+ {
+ var userName = string.Format("{0}:{1}", _oauthOptions.Pull.UserName, _oauthOptions.Pull.Password).ToBase64String();
+
+ // http调用结果
+ HttpResponse execute = null;
+ var map = parse(userEntity);
+ tenantId = tenantId != null && tenantId.Length > 0 ? tenantId : "1";
+ if (tenantId.Equals("default")) tenantId = "1";
+ map.Add("instId", tenantId);
+
+ // 得到userId
+ // String username = userEntity.get("id") != null && userEntity.get("id").toString().length() > 0 ? userEntity.get("id").toString() : null;
+
+ Dictionary jsonObject = null;
+ var resString = string.Empty;
+ var headers = new Dictionary();
+ headers.Add("Authorization", _oauthOptions.Pull.CredentialType + " " + userName);
+
+ if (method.Equals("create"))
+ {
+ resString = await (_oauthOptions.Pull.CreateRestAddress + "?appId=" + _oauthOptions.Pull.UserName).SetHeaders(headers).SetBody(map).PostAsStringAsync();
+ }
+ else if (method.Equals("update"))
+ {
+ resString = await (_oauthOptions.Pull.ReplaceRestAddress + "?appId=" + _oauthOptions.Pull.UserName).SetHeaders(headers).SetBody(map).PutAsStringAsync();
+ }
+ else if (method.Equals("delete"))
+ {
+ resString = await (_oauthOptions.Pull.DeleteRestAddress + "?appId=" + _oauthOptions.Pull.UserName).SetHeaders(headers).SetBody(map).DeleteAsStringAsync();
+ }
+ else if (method.Equals("modifyPassword"))
+ {
+ resString = await (_oauthOptions.Pull.ChangePasswordRestAddress + "?appId=" + _oauthOptions.Pull.UserName).SetHeaders(headers).SetBody(map).PostAsStringAsync();
+ }
+
+ // else if (method.Equals("modifyPassword")) {
+ // jsonObject = HttpUtil.httpRequest(_oauthOptions.Pull.getGetRestAddress() + username
+ // , "GET"
+ // , null, _oauthOptions.Pull.getCredentialType() + " " + _oauthOptions.Pull.getUserName() + "Og==" + _oauthOptions.Pull.getPassword()
+ // , null);
+ // }
+ }
+ }
+ catch (Exception e)
+ {
+
+ }
+ }
+
+ private Dictionary parse(UserEntity userEntity)
+ {
+ var map = new Dictionary();
+
+ // map.Add("id", userEntity.get("id"));
+ map.Add("username", userEntity.Account);
+ map.Add("password", userEntity.Password);
+ map.Add("mobile", userEntity.MobilePhone);
+ map.Add("email", userEntity.Email);
+ map.Add("gender", (int)userEntity.Gender == 1 ? 2 : 1);
+ map.Add("createdBy", userEntity.CreatorUserId);
+ map.Add("createdDate", userEntity.CreatorTime);
+ map.Add("modifiedBy", userEntity.LastModifyUserId);
+ map.Add("modifiedDate", userEntity.LastModifyTime);
+ map.Add("displayName", userEntity.RealName);
+
+ // map.Add("managerId", userEntity.get("managerId"));
+ // map.Add("departmentId", userEntity.get("organizeId"));
+ map.Add("loginCount", userEntity.LogSuccessCount);
+ map.Add("badPasswordCount", userEntity.LogErrorCount);
+ map.Add("lastLoginIp", userEntity.LastLogIP);
+ map.Add("lastLoginTime", userEntity.LastLogTime);
+ map.Add("status", userEntity.EnabledMark != null ? (userEntity.EnabledMark == 1 ? 1 : 4) : 4);
+ return map;
+ }
+
+ ///
+ /// 根据单点服务端消息 同步用户信息到数据库.
+ ///
+ ///
+ [NonAction]
+ public async Task Receive(string message)
+ {
+ bool isSuccess;
+ var map = new Dictionary();
+ try
+ {
+ var mqMessage = message.ToObject();
+
+ // 转成用户实体类
+ var userInfo = mqMessage.content.ToObject();
+ var userEntity = new UserEntity();
+ userEntity.Id = userInfo.id;
+ userEntity.Account = userInfo.username;
+ userEntity.MobilePhone = userInfo.mobile;
+ userEntity.Email = userInfo.email;
+ userEntity.Gender = userInfo.gender;
+ userEntity.CreatorTime = userInfo.createdDate.IsNullOrWhiteSpace() ? null : userInfo.createdDate?.ParseToLong().TimeStampToDateTime();
+ userEntity.CreatorUserId = userInfo.createdBy;
+ userEntity.LastModifyUserId = userInfo.modifiedBy;
+ userEntity.LastModifyTime = userInfo.modifiedDate.IsNullOrWhiteSpace() ? null : userInfo.modifiedDate?.ParseToLong().TimeStampToDateTime();
+ userEntity.RealName = userInfo.displayName;
+ userEntity.LogSuccessCount = userInfo.loginCount;
+ userEntity.LogErrorCount = userInfo.badPasswordCount;
+ userEntity.LastLogIP = userInfo.lastLoginIp;
+ userEntity.LastLogTime = userInfo.lastLoginTime.IsNullOrWhiteSpace() ? null : userInfo.lastLoginTime?.ParseToLong().TimeStampToDateTime();
+ userEntity.EnabledMark = userInfo.status == 1 ? 1 : 0;
+ userEntity.HeadIcon = "001.png";
+
+ if (_tenant.MultiTenancy)
+ {
+ ConnectionConfigOptions options = new ConnectionConfigOptions();
+ var interFace = string.Format("{0}{1}", _tenant.MultiTenancyDBInterFace, userInfo.instId);
+ var response = interFace.GetAsStringAsync().Result;
+ var result = response.ToObject>();
+ if (result.code != 200)
+ {
+ throw Oops.Oh(result.msg);
+ }
+ else if (result.data.dotnet == null && result.data.linkList == null)
+ {
+ throw Oops.Oh(ErrorCode.D1025);
+ }
+ else
+ {
+ if (result.data.linkList == null || result.data.linkList?.Count == 0)
+ {
+ options = JNPFTenantExtensions.GetLinkToOrdinary(userInfo.instId, result.data.dotnet);
+ }
+ else if (result.data.dotnet == null)
+ {
+ options = JNPFTenantExtensions.GetLinkToCustom(userInfo.instId, result.data.linkList);
+ }
+ }
+ if (!"default".Equals(userInfo.instId) && _tenant.MultiTenancyType.Equals("COLUMN"))
+ {
+ _sqlSugarClient.QueryFilter.AddTableFilter(it => it.TenantId == userInfo.instId);
+ }
+ else
+ {
+ _sqlSugarClient.AddConnection(JNPFTenantExtensions.GetConfig(options));
+ _sqlSugarClient.ChangeDatabase(userInfo.instId);
+ }
+ }
+
+ isSuccess = await process(userEntity, mqMessage.actionType, userInfo.instId);
+ }
+ catch (Exception e)
+ {
+ // _logger.error("同步用户失败", e);
+ isSuccess = false;
+ }
+
+ if (!isSuccess)
+ {
+ // _logger.info("消息消费失败:" + message);
+ }
+ else
+ {
+ // _logger.debug("同步用户信息, {}", JSONObject.toJSONString(map));
+ }
+
+ return isSuccess;
+ }
+
+ ///
+ /// 保存到数据库处理逻辑.
+ ///
+ ///
+ ///
+ ///
+ private async Task process(UserEntity entity, string actionType, string instId)
+ {
+ if (actionType.Equals("CREATE_ACTION"))
+ {
+ if (_sqlSugarClient.Queryable().Any(x => x.Account.Equals(entity.Account) && x.DeleteMark == null)) return true;
+ entity.Secretkey = Guid.NewGuid().ToString();
+ entity.Password = MD5Encryption.Encrypt(MD5Encryption.Encrypt(CommonConst.DEFAULTPASSWORD) + entity.Secretkey);
+
+ UserRelationEntity? entityRelation = new UserRelationEntity();
+ entityRelation.Id = SnowflakeIdHelper.NextId();
+ entityRelation.ObjectType = "Organize";
+ entityRelation.ObjectId = _sqlSugarClient.Queryable().First(x => x.ParentId.Equals("-1")).Id;
+ entityRelation.SortCode = 0;
+ entityRelation.UserId = entity.Id;
+ entityRelation.CreatorTime = DateTime.Now;
+ entityRelation.CreatorUserId = entity.CreatorUserId;
+ _sqlSugarClient.Insertable(entityRelation).ExecuteCommand(); // 批量新增用户关系
+
+ // 新增用户记录
+ return await _sqlSugarClient.Insertable(entity).CallEntityMethod(m => m.Create()).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync() > 0;
+ }
+ else if (actionType.Equals("UPDATE_ACTION"))
+ {
+ var oldEntity = await _sqlSugarClient.Queryable().FirstAsync(x => x.Account.Equals(entity.Account) && x.DeleteMark == null);
+ entity.Id = oldEntity.Id;
+ return await _sqlSugarClient.Updateable(entity).CallEntityMethod(m => m.LastModify()).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync() > 0;
+ }
+ else if (actionType.Equals("DELETE_ACTION"))
+ {
+ var oldEntity = await _sqlSugarClient.Queryable().FirstAsync(x => x.Account.Equals(entity.Account) && x.DeleteMark == null);
+ oldEntity.EnabledMark = 0;
+
+ // 同步删除用户 只能 该状态为 : 禁用
+ return await _sqlSugarClient.Updateable(oldEntity).CallEntityMethod(m => m.LastModify()).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync() > 0;
+
+ }
+ else if (actionType.Equals("PASSWORD_ACTION"))
+ {
+ return await _sqlSugarClient.Updateable().SetColumns(it => new UserEntity()
+ {
+ Password = entity.Password,
+ ChangePasswordDate = SqlFunc.GetDate(),
+ LastModifyUserId = _userManager.UserId,
+ LastModifyTime = SqlFunc.GetDate()
+ }).Where(it => it.Id == entity.Id).ExecuteCommandAsync() > 0;
+ }
+ else
+ {
+ //_logger.info("Other Action , will sikp it ...");
+ }
+
+ return true;
+ }
+
+ #endregion
}
\ No newline at end of file
diff --git a/system/Tnb.Systems/System/CommonWordsService.cs b/system/Tnb.Systems/System/CommonWordsService.cs
new file mode 100644
index 00000000..89844499
--- /dev/null
+++ b/system/Tnb.Systems/System/CommonWordsService.cs
@@ -0,0 +1,184 @@
+using JNPF.Common.Core.Manager;
+using JNPF.Common.Enums;
+using JNPF.Common.Extension;
+using JNPF.Common.Filter;
+using JNPF.DependencyInjection;
+using JNPF.DynamicApiController;
+using JNPF.FriendlyException;
+using JNPF.Systems.Entitys.Dto.System.CommonWords;
+using JNPF.Systems.Entitys.Entity.System;
+using JNPF.Systems.Entitys.System;
+using Mapster;
+using Microsoft.AspNetCore.Mvc;
+using SqlSugar;
+
+namespace JNPF.Systems.System;
+
+///
+/// 常用语.
+///
+[ApiDescriptionSettings(Tag = "System", Name = "CommonWords", Order = 200)]
+[Route("api/system/[controller]")]
+public class CommonWordsService : IDynamicApiController, ITransient
+{
+ private readonly ISqlSugarRepository _repository;
+ private readonly IUserManager _userManager;
+
+ ///
+ /// 初始化一个类型的新实例.
+ ///
+ public CommonWordsService(
+ ISqlSugarRepository repository,
+ IUserManager userManager)
+ {
+ _repository = repository;
+ _userManager = userManager;
+ }
+
+ #region Get
+
+ ///
+ /// 列表.
+ ///
+ /// 参数.
+ ///
+ [HttpGet("")]
+ public async Task GetList([FromQuery] PageInputBase input)
+ {
+ var list = await _repository.AsSugarClient().Queryable()
+ .Where(a => a.CommonWordsType == 0 && a.DeleteMark == null)
+ .WhereIF(input.keyword.IsNotEmptyOrNull(), a => SqlFunc.ToString(a.SystemNames).Contains(input.keyword) || SqlFunc.ToString(a.CommonWordsText).Contains(input.keyword))
+ .OrderBy(a => a.SortCode).OrderBy(a => a.CreatorTime, OrderByType.Desc)
+ .Select(a => new CommonWordsOutput()
+ {
+ id = a.Id,
+ systemNames = SqlFunc.ToString(a.SystemNames),
+ commonWordsText = SqlFunc.ToString(a.CommonWordsText),
+ sortCode = a.SortCode,
+ enabledMark = a.EnabledMark,
+ }).ToPagedListAsync(input.currentPage, input.pageSize);
+ return PageResult.SqlSugarPageResult(list);
+ }
+
+ ///
+ /// 获取信息.
+ ///
+ /// 主键id.
+ ///
+ [HttpGet("{id}")]
+ public async Task GetInfo(string id)
+ {
+ var data = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
+ var output = new CommonWordsInput();
+ if (data.IsNotEmptyOrNull())
+ {
+ output.id = data.Id;
+ output.commonWordsText = data.CommonWordsText;
+ output.sortCode = data.SortCode;
+ output.enabledMark = data.EnabledMark;
+ output.commonWordsType = data.CommonWordsType;
+ foreach (var item in data.SystemIds.Split(","))
+ {
+ var systemEntity = await _repository.AsSugarClient().Queryable().FirstAsync(x => x.Id == item && x.EnabledMark == 1 && x.DeleteMark == null);
+ if (systemEntity.IsNotEmptyOrNull())
+ {
+ output.systemIds.Add(systemEntity.Id);
+ output.systemNames.Add(systemEntity.FullName);
+ }
+ }
+ }
+ return output;
+ }
+
+ ///
+ /// 下拉列表.
+ ///
+ ///
+ [HttpGet("Selector")]
+ public async Task GetSelector()
+ {
+ var list = await _repository.AsSugarClient().Queryable()
+ .Where(a => (a.CommonWordsType == 0 || a.CreatorUserId == _userManager.UserId) && a.SystemIds.Contains(_userManager.User.SystemId) && a.EnabledMark == 1 && a.DeleteMark == null)
+ .OrderBy(a => a.CommonWordsType, OrderByType.Desc).OrderBy(a => a.SortCode).OrderBy(a => a.CreatorTime, OrderByType.Desc)
+ .Select(a => new CommonWordsOutput()
+ {
+ id = a.Id,
+ systemNames = SqlFunc.ToString(a.SystemNames),
+ commonWordsText = SqlFunc.ToString(a.CommonWordsText),
+ sortCode = a.SortCode,
+ enabledMark = a.EnabledMark,
+ commonWordsType = a.CommonWordsType,
+ }).ToListAsync();
+ return new { list = list };
+ }
+ #endregion
+
+ #region Post
+
+ ///
+ /// 新建.
+ ///
+ /// 实体对象.
+ ///
+ [HttpPost("")]
+ public async Task Create([FromBody] CommonWordsInput input)
+ {
+ var entity = input.Adapt();
+ if (input.systemIds.Any())
+ {
+ entity.SystemIds = string.Join(",", input.systemIds);
+ entity.SystemNames = string.Join(",", input.systemNames);
+ }
+ else
+ {
+ entity.SystemIds = _userManager.User.SystemId;
+ entity.SystemNames = _repository.AsSugarClient().Queryable().First(x => x.Id == _userManager.User.SystemId && x.DeleteMark == null).FullName;
+ }
+ var isOk = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
+ if (isOk < 1)
+ throw Oops.Oh(ErrorCode.COM1000);
+ }
+
+ ///
+ /// 修改.
+ ///
+ /// 主键值.
+ /// 实体对象.
+ ///
+ [HttpPut("{id}")]
+ public async Task Update(string id, [FromBody] CommonWordsInput input)
+ {
+ var entity = input.Adapt();
+ if (input.systemIds.Any())
+ {
+ entity.SystemIds = string.Join(",", input.systemIds);
+ entity.SystemNames = string.Join(",", input.systemNames);
+ }
+ else
+ {
+ entity.SystemIds = _userManager.User.SystemId;
+ entity.SystemNames = _repository.AsSugarClient().Queryable().First(x => x.Id == _userManager.User.SystemId && x.DeleteMark == null).FullName;
+ }
+ var isOk = await _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync();
+ if (!isOk)
+ throw Oops.Oh(ErrorCode.COM1001);
+ }
+
+ ///
+ /// 删除.
+ ///
+ /// 主键.
+ ///
+ [HttpDelete("{id}")]
+ public async Task Delete(string id)
+ {
+ var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
+ if (entity == null)
+ throw Oops.Oh(ErrorCode.COM1005);
+ var isOk = await _repository.AsUpdateable(entity).CallEntityMethod(m => m.Delete()).UpdateColumns(it => new { it.DeleteMark, it.DeleteTime, it.DeleteUserId }).ExecuteCommandHasChangeAsync();
+ if (!isOk)
+ throw Oops.Oh(ErrorCode.COM1002);
+ }
+
+ #endregion
+}
diff --git a/system/Tnb.Systems/System/DataBaseService.cs b/system/Tnb.Systems/System/DataBaseService.cs
index 62904074..35c1bb6d 100644
--- a/system/Tnb.Systems/System/DataBaseService.cs
+++ b/system/Tnb.Systems/System/DataBaseService.cs
@@ -1,11 +1,7 @@
-using System.ArrayExtensions;
-using System.Collections;
-using System.ComponentModel.DataAnnotations.Schema;
+using System.Collections;
using System.Data;
using System.Text;
-using System.Text.RegularExpressions;
using JNPF.Common.Configuration;
-using JNPF.Common.Contracts;
using JNPF.Common.Core.Manager;
using JNPF.Common.Core.Manager.Files;
using JNPF.Common.Dtos.DataBase;
@@ -26,8 +22,6 @@ using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
-using NPOI.SS.Formula.Functions;
-using Org.BouncyCastle.Asn1.Cms;
using SqlSugar;
namespace JNPF.Systems;
@@ -101,30 +95,41 @@ public class DataBaseService : IDynamicApiController, ITransient
/// 过滤条件.
///
[HttpGet("{id}/Tables")]
- public async Task GetList(string id, [FromQuery] KeywordInput input)
+ public async Task GetList(string id, [FromQuery] PageInputBase input)
{
- var link = await _dbLinkService.GetInfo(id);
- var tenantLink = link ?? _dataBaseManager.GetTenantDbLink(_userManager.TenantId, _userManager.TenantDbName);
- var tables = _dataBaseManager.GetDBTableList(tenantLink);
- //tables = tables.Where((x, i) => tables.FindIndex(z => z.Name == x.Name) == i).ToList();
- //var output = tables.Adapt>();
- if (!string.IsNullOrEmpty(input.keyword))
+ try
{
- var keyword = input.keyword.ToLower();
- tables = tables.FindAll(d => d.table.ToLower().Contains(keyword) || (d.tableName.IsNotEmptyOrNull() && d.tableName.ToLower().Contains(keyword)));
+ var link = await _dbLinkService.GetInfo(id);
+ var tenantLink = link ?? _dataBaseManager.GetTenantDbLink(_userManager.TenantId, _userManager.TenantDbName);
+ var tables = _dataBaseManager.GetTableInfos(tenantLink);
+ tables = tables.Where((x, i) => tables.FindIndex(z => z.Name == x.Name) == i).ToList();//去重
+ var output = tables.Adapt>();
+ if (!string.IsNullOrEmpty(input.keyword))
+ output = output.FindAll(d => d.table.ToLower().Contains(input.keyword.ToLower()) || (d.tableName.IsNotEmptyOrNull() && d.tableName.ToLower().Contains(input.keyword.ToLower())));
+ return PageResult.SqlSugarPageResult(new SqlSugarPagedList()
+ {
+ list = output.OrderBy(x => x.table).Skip((input.currentPage - 1) * input.pageSize).Take(input.pageSize).OrderBy(x => x.table).ToList(),
+ pagination = new Pagination()
+ {
+ CurrentPage = input.currentPage,
+ PageSize = input.pageSize,
+ Total = output.Count
+ }
+ });
}
- if (tenantLink.DbType.ToLower().Equals("dm"))
+ catch (Exception ex)
{
- GetTableCount(tables, tenantLink);
+ return PageResult.SqlSugarPageResult(new SqlSugarPagedList()
+ {
+ list = new List(),
+ pagination = new Pagination()
+ {
+ CurrentPage = input.currentPage,
+ PageSize = input.pageSize,
+ Total = 0
+ }
+ });
}
- return new { list = tables.OrderBy(x => x.table).ToList() };
- //try
- //{
- //}
- //catch (Exception ex)
- //{
- // return new { list = new List() };
- //}
}
///
@@ -186,8 +191,7 @@ public class DataBaseService : IDynamicApiController, ITransient
if (string.IsNullOrEmpty(tableName)) return new PageResult();
var tenantLink = link ?? _dataBaseManager.GetTenantDbLink(_userManager.TenantId, _userManager.TenantDbName);
var output = _dataBaseManager.GetDataBaseTableInfo(tenantLink, tableName);
- var data = _dataBaseManager.GetData(tenantLink, tableName);
- output.hasTableData = data.Rows.Count > 0;
+ output.hasTableData = _dataBaseManager.IsAnyData(tenantLink, tableName);
return output;
}
@@ -262,6 +266,8 @@ public class DataBaseService : IDynamicApiController, ITransient
var tenantLink = link ?? _dataBaseManager.GetTenantDbLink(_userManager.TenantId, _userManager.TenantDbName);
if (_dataBaseManager.IsAnyTable(tenantLink, input.tableInfo.newTable))
throw Oops.Oh(ErrorCode.D1503);
+ if (input.tableInfo.newTable.Length >= 30) throw Oops.Oh(ErrorCode.D1514);
+ if (input.tableFieldList.Any(x => x.field.Length >= 30)) throw Oops.Oh(ErrorCode.D1515);
var tableInfo = input.tableInfo.Adapt();
tableInfo.table = input.tableInfo.newTable;
var tableFieldList = input.tableFieldList.Adapt>();
@@ -280,10 +286,12 @@ public class DataBaseService : IDynamicApiController, ITransient
public async Task Update(string linkId, [FromBody] DatabaseTableUpInput input)
{
var link = await _dbLinkService.GetInfo(linkId);
+ if (input.tableInfo.newTable.Length >= 30) throw Oops.Oh(ErrorCode.D1514);
+ if (input.tableFieldList.Any(x => x.field.Length >= 30)) throw Oops.Oh(ErrorCode.D1515);
var tenantLink = link ?? _dataBaseManager.GetTenantDbLink(_userManager.TenantId, _userManager.TenantDbName);
var oldFieldList = _dataBaseManager.GetFieldList(tenantLink, input.tableInfo.table).Adapt>();
oldFieldList = _dataBaseManager.ViewDataTypeConversion(oldFieldList, _dataBaseManager.ToDbType(tenantLink.DbType));
- var oldTableInfo = _dataBaseManager.GetDBTableList(tenantLink).Find(m => m.table == input.tableInfo.table).Adapt();
+ var oldTableInfo = _dataBaseManager.GetTableInfos(tenantLink).Find(m => m.Name == input.tableInfo.table).Adapt();
var data = _dataBaseManager.GetData(tenantLink, input.tableInfo.table);
if (data.Rows.Count > 0)
throw Oops.Oh(ErrorCode.D1508);
@@ -313,6 +321,7 @@ public class DataBaseService : IDynamicApiController, ITransient
{
try
{
+ if (input.tableFieldList.Any(x => x.field.Length >= 30)) throw Oops.Oh(ErrorCode.D1515);
var link = await _dbLinkService.GetInfo(linkId);
var tenantLink = link ?? _dataBaseManager.GetTenantDbLink(_userManager.TenantId, _userManager.TenantDbName);
_dataBaseManager.AddTableColumn(tenantLink, input.tableInfo.table, input.tableFieldList.Adapt>());
@@ -631,7 +640,7 @@ public class DataBaseService : IDynamicApiController, ITransient
{"tool_", "Tnb.EquipMgr.Entities" },
{"qc_", "Tnb.QcMgr.Entities" },
};
- var allTables = sugar.DbMaintenance.GetTableInfoList().WhereIF(!string.IsNullOrEmpty(tbName), t=>t.Name == tbName);
+ var allTables = sugar.DbMaintenance.GetTableInfoList().WhereIF(!string.IsNullOrEmpty(tbName), t => t.Name == tbName);
foreach (var tbl in allTables)
{
var prefix = tbl.Name.Split('_')[0] + "_";
diff --git a/system/Tnb.Systems/System/DataInterfaceService.cs b/system/Tnb.Systems/System/DataInterfaceService.cs
index ab5b29ba..e8403e0d 100644
--- a/system/Tnb.Systems/System/DataInterfaceService.cs
+++ b/system/Tnb.Systems/System/DataInterfaceService.cs
@@ -21,6 +21,7 @@ using JNPF.Common.Security;
using JNPF.DatabaseAccessor;
using JNPF.DependencyInjection;
using JNPF.DynamicApiController;
+using JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
using JNPF.Extras.Thirdparty.JSEngine;
using JNPF.FriendlyException;
using JNPF.LinqBuilder;
@@ -506,19 +507,65 @@ public class DataInterfaceService : IDataInterfaceService, IDynamicApiController
ConnectionString = string.Format($"{App.Configuration["ConnectionStrings:DefaultConnection"]}", result.data.dotnet)
});
}
-
- _sqlSugarClient.ChangeDatabase(tenantId);
+ if (!"default".Equals(tenantId) && KeyVariable.MultiTenancyType.Equals("COLUMN"))
+ {
+ _sqlSugarClient.QueryFilter.AddTableFilter(it => it.TenantId == tenantId);
+ }
+ else
+ {
+ _sqlSugarClient.ChangeDatabase(tenantId);
+ }
}
var interfaceOauthEntity = await _sqlSugarClient.Queryable().FirstAsync(x => x.AppId == appId && x.DeleteMark == null && x.EnabledMark == 1);
if (interfaceOauthEntity == null) return null;
var ymDate = DateTime.Now.ParseToUnixTime().ToString();
var authorization = GetVerifySignature(interfaceOauthEntity, intefaceId, ymDate);
- return new
- {
+ return new {
YmDate = ymDate,
Authorization = authorization,
};
}
+
+ ///
+ /// 复制.
+ ///
+ /// 主键值.
+ ///
+ [HttpPost("{id}/Actions/Copy")]
+ public async Task ActionsCopy(string id)
+ {
+ var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
+ if (entity == null)
+ throw Oops.Oh(ErrorCode.COM1005);
+ var random = RandomExtensions.NextLetterAndNumberString(new Random(), 5).ToLower();
+ entity.FullName = string.Format("{0}.副本{1}", entity.FullName, random);
+ entity.EnCode = string.Format("{0}{1}", entity.EnCode, random);
+ if (entity.FullName.Length >= 50 || entity.EnCode.Length >= 50)
+ throw Oops.Oh(ErrorCode.COM1009);
+ entity.EnabledMark = 0;
+ var isOk = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
+ if (isOk < 1)
+ throw Oops.Oh(ErrorCode.COM1000);
+ }
+
+ ///
+ /// 预览接口字段.
+ ///
+ ///
+ ///
+ [HttpPost("{id}/Actions/GetFields")]
+ [UnitOfWork]
+ public async Task GetFields(string id, [FromBody] DataInterfacePreviewInput input)
+ {
+ try
+ {
+ return (await Preview(id, input)).ToObject>>().FirstOrDefault().Keys.ToList();
+ }
+ catch (Exception e)
+ {
+ throw Oops.Oh(ErrorCode.COM1020);
+ }
+ }
#endregion
#region PublicMethod
@@ -549,7 +596,7 @@ public class DataInterfaceService : IDataInterfaceService, IDynamicApiController
/// 根据不同类型请求接口.
///
///
- /// 0 : 分页 1 :详情 ,其他 原始.
+ /// 0 : 分页 1 :详情 2:数据视图 ,其他 原始.
///
///
///
@@ -579,36 +626,61 @@ public class DataInterfaceService : IDataInterfaceService, IDynamicApiController
});
}
- _sqlSugarClient.ChangeDatabase(tenantId);
+ if (!"default".Equals(tenantId) && KeyVariable.MultiTenancyType.Equals("COLUMN"))
+ {
+ _sqlSugarClient.QueryFilter.AddTableFilter(it => it.TenantId == tenantId);
+ }
+ else
+ {
+ _sqlSugarClient.ChangeDatabase(tenantId);
+ }
_configId = tenantId;
_dbName = result.data.dotnet;
}
- var data = await _sqlSugarClient.Queryable().FirstAsync(x => x.Id == id && x.DeleteMark == null);
+ var data = await _sqlSugarClient.CopyNew().Queryable().FirstAsync(x => x.Id == id && x.DeleteMark == null);
if (data == null)
throw Oops.Oh(ErrorCode.COM1005);
// 远端数据(sql过滤)
if (input.IsNotEmptyOrNull())
{
- var columnList = new List();
- if (input.keyword.IsNotEmptyOrNull())
- input.columnOptions.Split(",").ToList().ForEach(x => columnList.Add(string.Format("{0} like '%{1}%'", x, input.keyword)));
-
- if (columnList.Any() && !string.IsNullOrWhiteSpace(input.keyword))
- data.Query = string.Format("select * from ({0}) t where {1} ", data.Query.TrimEnd(';'), string.Join(" or ", columnList));
- else if (!string.IsNullOrWhiteSpace(input.relationField) && !string.IsNullOrWhiteSpace(input.keyword))
- data.Query = string.Format("select * from ({0}) t where {1} like '%{2}%' ", data.Query.TrimEnd(';'), input.relationField, input.keyword);
-
- if (!string.IsNullOrWhiteSpace(input.propsValue) && !string.IsNullOrWhiteSpace(input.id))
- data.Query = string.Format("select * from ({0}) t where {1} = '{2}' ", data.Query.TrimEnd(';'), input.propsValue, input.id);
- if (!string.IsNullOrWhiteSpace(input.propsValue) && input.ids.Any())
- data.Query = string.Format("select * from ({0}) t where {1} in ('{2}') ", data.Query.TrimEnd(';'), input.propsValue, string.Join("','", input.ids));
- if (input.columnOptions.IsNotEmptyOrNull() && !string.IsNullOrWhiteSpace(input.keyword))
+ if (type == 2 && !2.Equals(data.DataType) && (input.queryJson.IsNotEmptyOrNull() || input.sidx.IsNotEmptyOrNull()))
{
- var whereStr = new List();
- input.columnOptions.Split(",").ToList().ForEach(item => whereStr.Add(string.Format(" {0} like '%{1}%' ", item, input.keyword)));
- data.Query = string.Format("select * from ({0}) t where {1} ", data.Query.TrimEnd(';'), string.Join(" or ", whereStr));
+ if (input.queryJson.IsNotEmptyOrNull())
+ {
+ var sqlFields = input.queryJson.ToObject>();
+ var whereList = new List();
+ foreach (var item in sqlFields)
+ {
+ if (item.Key.Contains("jnpf_searchType_equals_")) whereList.Add(string.Format("{0} = '{1}' ", item.Key.Replace("jnpf_searchType_equals_", string.Empty), item.Value));
+ else whereList.Add(string.Format("{0} like '%{1}%' ", item.Key, item.Value));
+ }
+ data.Query = string.Format("select * from ({0}) t where {1} ", data.Query.TrimEnd(';'), string.Join(" and ", whereList));
+ }
+ if (input.sidx.IsNotEmptyOrNull()) data.Query = string.Format("{0} order by {1} {2}", data.Query.TrimEnd(';'), input.sidx, input.sort);
+ }
+ else
+ {
+ var columnList = new List();
+ if (input.keyword.IsNotEmptyOrNull())
+ input.columnOptions.Split(",").ToList().ForEach(x => columnList.Add(string.Format("{0} like '%{1}%'", x, input.keyword)));
+
+ if (columnList.Any() && !string.IsNullOrWhiteSpace(input.keyword))
+ data.Query = string.Format("select * from ({0}) t where {1} ", data.Query.TrimEnd(';'), string.Join(" or ", columnList));
+ else if (!string.IsNullOrWhiteSpace(input.relationField) && !string.IsNullOrWhiteSpace(input.keyword))
+ data.Query = string.Format("select * from ({0}) t where {1} like '%{2}%' ", data.Query.TrimEnd(';'), input.relationField, input.keyword);
+
+ if (!string.IsNullOrWhiteSpace(input.propsValue) && !string.IsNullOrWhiteSpace(input.id))
+ data.Query = string.Format("select * from ({0}) t where {1} = '{2}' ", data.Query.TrimEnd(';'), input.propsValue, input.id);
+ if (!string.IsNullOrWhiteSpace(input.propsValue) && input.ids.Any())
+ data.Query = string.Format("select * from ({0}) t where {1} in ('{2}') ", data.Query.TrimEnd(';'), input.propsValue, string.Join("','", input.ids));
+ if (input.columnOptions.IsNotEmptyOrNull() && !string.IsNullOrWhiteSpace(input.keyword))
+ {
+ var whereStr = new List();
+ input.columnOptions.Split(",").ToList().ForEach(item => whereStr.Add(string.Format(" {0} like '%{1}%' ", item, input.keyword)));
+ data.Query = string.Format("select * from ({0}) t where {1} ", data.Query.TrimEnd(';'), string.Join(" or ", whereStr));
+ }
}
if (input.paramList.IsNotEmptyOrNull() && input.paramList.Count > 0)
{
@@ -625,12 +697,11 @@ public class DataInterfaceService : IDataInterfaceService, IDynamicApiController
if (1.Equals(data.DataType))
{
var resTable = await GetData(data);
- if (type == 0)
+ if (type == 0 || type == 2)
{
// 分页
var dt = GetPageToDataTable(resTable, input.currentPage, input.pageSize);
- output = new
- {
+ output = new {
pagination = new PageResult()
{
currentPage = input.currentPage,
@@ -677,8 +748,7 @@ public class DataInterfaceService : IDataInterfaceService, IDynamicApiController
// });
//}
resList = resList.FindAll(x => x.Where(xx => xx.Value != null && xx.Value.Contains(input.keyword)).Any());
- output = new
- {
+ output = new {
pagination = new PageResult()
{
currentPage = input.currentPage,
@@ -699,6 +769,47 @@ public class DataInterfaceService : IDataInterfaceService, IDynamicApiController
return resList.FindAll(x => x.ContainsKey(input.propsValue) && x.Any(it => input.ids.Contains(it.Value)));
}
}
+ else if (type == 2)
+ {
+ if (input.queryJson.IsNotEmptyOrNull() || input.sidx.IsNotEmptyOrNull())
+ {
+ if (input.queryJson.IsNotEmptyOrNull())
+ {
+ var querList = input.queryJson.ToObject>();
+ foreach (var item in querList)
+ {
+ if (item.Key.Contains("jnpf_searchType_equals_")) resList = resList.Where(x => x[item.Key.Replace("jnpf_searchType_equals_", "")].Equals(item.Value)).ToList();
+ else resList = resList.Where(x => x[item.Key].Contains(item.Value)).ToList();
+ }
+ }
+ if (input.sidx.IsNotEmptyOrNull())
+ {
+ if (input.sort.Equals("desc")) resList = resList.OrderBy(x => x[input.sidx]).ToList();
+ else resList = resList.OrderByDescending(x => x[input.sidx]).ToList();
+ }
+ output = new {
+ pagination = new PageResult()
+ {
+ currentPage = input.currentPage,
+ pageSize = input.pageSize,
+ total = resList.Count
+ },
+ list = resList.Skip((input.currentPage - 1) * input.pageSize).Take(input.pageSize).ToList(),
+ };
+ }
+ else
+ {
+ output = new {
+ pagination = new PageResult()
+ {
+ currentPage = input.currentPage,
+ pageSize = input.pageSize,
+ total = resList.Count
+ },
+ list = resList.Skip((input.currentPage - 1) * input.pageSize).Take(input.pageSize).ToList(),
+ };
+ }
+ }
else
{
output = result;
@@ -800,12 +911,12 @@ public class DataInterfaceService : IDataInterfaceService, IDynamicApiController
}
else
{
- dataProcessingResults = resList.ToJsonString();
+ dataProcessingResults = resList;
}
break;
// 静态数据
case 2:
- dataProcessingResults = resList.ToJsonString();
+ dataProcessingResults = resList;
break;
}
if (!dataProcessingResults.IsNullOrEmpty())
@@ -868,11 +979,11 @@ public class DataInterfaceService : IDataInterfaceService, IDynamicApiController
var link = new DbLinkEntity();
if (!_sqlSugarClient.AsTenant().IsAnyConnection(_configId))
{
- link = await _sqlSugarClient.Queryable().FirstAsync(x => x.Id == dbLinkId && x.DeleteMark == null);
+ link = await _sqlSugarClient.CopyNew().Queryable().FirstAsync(x => x.Id == dbLinkId && x.DeleteMark == null);
}
else
{
- link = await _repository.AsSugarClient().Queryable().FirstAsync(x => x.Id == dbLinkId && x.DeleteMark == null);
+ link = await _repository.AsSugarClient().CopyNew().Queryable().FirstAsync(x => x.Id == dbLinkId && x.DeleteMark == null);
}
var tenantLink = link ?? await GetTenantDbLink();
@@ -880,7 +991,7 @@ public class DataInterfaceService : IDataInterfaceService, IDynamicApiController
sql = await GetSqlParameter(sql, parameter);
if (reqMethod.Equals("3"))
{
- return _dataBaseManager.GetInterFaceData(tenantLink, sql, parameter.ToArray());
+ return _dataBaseManager.GetInterFaceDataCopyNew(tenantLink, sql, parameter.ToArray());
}
else
{
@@ -914,16 +1025,23 @@ public class DataInterfaceService : IDataInterfaceService, IDynamicApiController
dicHerader[key.field] = key.defaultValue;
}
- switch (entity?.RequestMethod)
+ try
{
- case "6":
- result = (await entity.Path.SetHeaders(dicHerader).SetQueries(dic).GetAsStringAsync()).ToObject();
- break;
- case "7":
- result = (await entity.Path.SetHeaders(dicHerader).SetBody(dic).PostAsStringAsync()).ToObject();
- break;
+ switch (entity.RequestMethod)
+ {
+ case "6":
+ result = (await entity.Path.SetHeaders(dicHerader).SetQueries(dic).GetAsStringAsync()).ToObject();
+ break;
+ case "7":
+ result = (await entity.Path.SetHeaders(dicHerader).SetBody(dic).PostAsStringAsync()).ToObject();
+ break;
+ }
}
- return result.ContainsKey("data") ? result["data"].ToObject() : result;
+ catch (Exception e)
+ {
+ throw Oops.Oh(ErrorCode.COM1018);
+ }
+ return result.ContainsKey("data") && result["data"].IsNotEmptyOrNull() ? result["data"].ToObject() : result;
}
///
@@ -1158,7 +1276,14 @@ public class DataInterfaceService : IDataInterfaceService, IDynamicApiController
});
}
- _sqlSugarClient.ChangeDatabase(tenantId);
+ if (!"default".Equals(tenantId) && KeyVariable.MultiTenancyType.Equals("COLUMN"))
+ {
+ _sqlSugarClient.QueryFilter.AddTableFilter(it => it.TenantId == tenantId);
+ }
+ else
+ {
+ _sqlSugarClient.ChangeDatabase(tenantId);
+ }
_configId = tenantId;
_dbName = result.data.dotnet;
}
diff --git a/system/Tnb.Systems/System/DbLinkService.cs b/system/Tnb.Systems/System/DbLinkService.cs
index 6a337e44..3ead4d4b 100644
--- a/system/Tnb.Systems/System/DbLinkService.cs
+++ b/system/Tnb.Systems/System/DbLinkService.cs
@@ -13,7 +13,6 @@ using JNPF.Systems.Entitys.System;
using JNPF.Systems.Interfaces.System;
using Mapster;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Caching.Memory;
using SqlSugar;
namespace JNPF.Systems;
@@ -43,21 +42,17 @@ public class DbLinkService : IDbLinkService, IDynamicApiController, ITransient
///
private readonly IDataBaseManager _dataBaseManager;
- private readonly IMemoryCache _memCache;
-
///
/// 初始化一个类型的新实例.
///
public DbLinkService(
ISqlSugarRepository repository,
IDictionaryDataService dictionaryDataService,
- IDataBaseManager dataBaseManager,
- IMemoryCache memCache)
+ IDataBaseManager dataBaseManager)
{
_repository = repository;
_dictionaryDataService = dictionaryDataService;
_dataBaseManager = dataBaseManager;
- _memCache = memCache;
}
#region GET
@@ -318,7 +313,7 @@ public class DbLinkService : IDbLinkService, IDynamicApiController, ITransient
[NonAction]
public async Task GetInfo(string id)
{
- return await _repository.AsSugarClient().CopyNew().Queryable().FirstAsync(m => m.Id == id && m.DeleteMark == null);
+ return await _repository.GetFirstAsync(m => m.Id == id && m.DeleteMark == null);
}
#endregion
}
\ No newline at end of file
diff --git a/system/Tnb.Systems/System/InterfaceOauthService.cs b/system/Tnb.Systems/System/InterfaceOauthService.cs
index 52c9ec54..97525968 100644
--- a/system/Tnb.Systems/System/InterfaceOauthService.cs
+++ b/system/Tnb.Systems/System/InterfaceOauthService.cs
@@ -16,220 +16,221 @@ using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
-namespace JNPF.Systems.System
+namespace JNPF.Systems.System;
+
+///
+/// 接口认证
+/// 版 本:V3.2
+/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
+ /// 日 期:2021-06-01.
+///
+[ApiDescriptionSettings(Tag = "System", Name = "InterfaceOauth", Order = 202)]
+[Route("api/system/[controller]")]
+public class InterfaceOauthService : IDynamicApiController, ITransient
{
///
- /// 接口认证
- /// 版 本:V3.2
- /// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
- /// 日 期:2021-06-01.
+ /// 服务基本仓储.
///
- [ApiDescriptionSettings(Tag = "System", Name = "InterfaceOauth", Order = 202)]
- [Route("api/system/[controller]")]
- public class InterfaceOauthService : IDynamicApiController, ITransient
+ private readonly ISqlSugarRepository _repository;
+
+ ///
+ /// 用户管理.
+ ///
+ private readonly IUserManager _userManager;
+
+ ///
+ /// 初始化一个类型的新实例.
+ ///
+ public InterfaceOauthService(
+ ISqlSugarRepository repository,
+ IUserManager userManager)
{
- ///
- /// 服务基本仓储.
- ///
- private readonly ISqlSugarRepository _repository;
+ _repository = repository;
+ _userManager = userManager;
+ }
- ///
- /// 用户管理.
- ///
- private readonly IUserManager _userManager;
+ #region Get
- ///
- /// 初始化一个类型的新实例.
- ///
- public InterfaceOauthService(
- ISqlSugarRepository repository,
- IUserManager userManager)
+ ///
+ /// 信息.
+ ///
+ /// 请求参数.
+ ///
+ [HttpGet("{id}")]
+ public async Task GetInfo(string id)
+ {
+ var info = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
+ var output = info.Adapt();
+ if (info.IsNotEmptyOrNull() && info.DataInterfaceIds.IsNotEmptyOrNull())
{
- _repository = repository;
- _userManager = userManager;
- }
-
- #region Get
-
- ///
- /// 信息.
- ///
- /// 请求参数.
- ///
- [HttpGet("{id}")]
- public async Task GetInfo(string id)
- {
- var info = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
- var output = info.Adapt();
- if (info.IsNotEmptyOrNull() && info.DataInterfaceIds.IsNotEmptyOrNull())
- {
- var ids = info.DataInterfaceIds.Split(",");
- output.list = await _repository.AsSugarClient().Queryable()
- .Where(a => ids.Contains(a.Id))
- .Select(a => new DataInterfaceListOutput
- {
- id = a.Id,
- fullName = a.FullName,
- enCode = a.EnCode,
- path = a.Path,
- requestParameters = a.RequestParameters,
- dataType = a.DataType,
- requestMethod = SqlFunc.IF(a.RequestMethod.Equals("1")).Return("新增").ElseIF(a.RequestMethod.Equals("2")).Return("修改")
- .ElseIF(a.RequestMethod.Equals("3")).Return("查询").ElseIF(a.RequestMethod.Equals("4")).Return("删除")
- .ElseIF(a.RequestMethod.Equals("5")).Return("存储过程").ElseIF(a.RequestMethod.Equals("6")).Return("Get")
- .End("Post")
- }).ToListAsync();
- }
- return output;
- }
-
- ///
- /// 列表.
- ///
- [HttpGet("")]
- public async Task GetList([FromQuery] PageInputBase input)
- {
- var list = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == a.CreatorUserId))
- .Where(a => a.DeleteMark == null)
- .WhereIF(!string.IsNullOrEmpty(input.keyword), a => a.AppId.Contains(input.keyword) || a.AppName.Contains(input.keyword))
- .OrderBy(a => a.SortCode).OrderBy(a => a.CreatorTime, OrderByType.Desc)
- .Select((a, b) => new InterfaceOauthListOutput
- {
- id = a.Id,
- lastModifyTime = a.LastModifyTime,
- enabledMark = a.EnabledMark,
- creatorUser = SqlFunc.MergeString(b.RealName, "/", b.Account),
- appId = a.AppId,
- appName = a.AppName,
- usefulLife = a.UsefulLife,
- sortCode = a.SortCode,
- creatorTime = a.CreatorTime
- }).ToPagedListAsync(input.currentPage, input.pageSize);
- return PageResult.SqlSugarPageResult(list);
- }
-
- ///
- /// 获取秘钥.
- ///
- ///
- [HttpGet("getAppSecret")]
- public async Task GetAppSecret()
- {
- return Guid.NewGuid().ToString().Replace("-", string.Empty);
- }
-
- ///
- /// 日志.
- ///
- ///
- ///
- ///
- [HttpGet("dataInterfaceLog/{id}")]
- public async Task GetList(string id, [FromQuery] DataInterfaceLogListQuery input)
- {
- var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
- var whereLambda = LinqExpression.And();
- if (!input.startTime.IsNullOrEmpty() && !input.endTime.IsNullOrEmpty())
- {
- var startTime = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 00:00:00}", input.startTime?.TimeStampToDateTime()));
- var endTime = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 23:59:59}", input.endTime?.TimeStampToDateTime()));
- whereLambda = whereLambda.And(a => SqlFunc.Between(a.invokTime, startTime, endTime));
- }
- var list = await _repository.AsSugarClient().Queryable((a, b, c) =>
- new JoinQueryInfos(JoinType.Left, b.Id == a.UserId, JoinType.Left, a.InvokId == c.Id))
- .Where(a => a.OauthAppId == entity.AppId)
- .WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.UserId.Contains(input.keyword) || a.InvokIp.Contains(input.keyword))
- .Select((a, b, c) => new DataInterfaceLogListOutput
+ var ids = info.DataInterfaceIds.Split(",");
+ output.list = await _repository.AsSugarClient().Queryable()
+ .Where(a => ids.Contains(a.Id))
+ .Select(a => new DataInterfaceListOutput
{
id = a.Id,
- fullName = c.FullName,
- enCode = c.EnCode,
- invokDevice = a.InvokDevice,
- invokIp = a.InvokIp,
- userId = SqlFunc.MergeString(b.RealName, "/", b.Account),
- invokTime = a.InvokTime,
- invokType = a.InvokType,
- invokWasteTime = a.InvokWasteTime
- }).MergeTable().Where(whereLambda).OrderBy(a => a.invokTime).ToPagedListAsync(input.currentPage, input.pageSize);
- return PageResult.SqlSugarPageResult(list);
+ fullName = a.FullName,
+ enCode = a.EnCode,
+ path = a.Path,
+ requestParameters = a.RequestParameters,
+ dataType = a.DataType,
+ requestMethod = SqlFunc.IF(a.RequestMethod.Equals("1")).Return("新增").ElseIF(a.RequestMethod.Equals("2")).Return("修改")
+ .ElseIF(a.RequestMethod.Equals("3")).Return("查询").ElseIF(a.RequestMethod.Equals("4")).Return("删除")
+ .ElseIF(a.RequestMethod.Equals("5")).Return("存储过程").ElseIF(a.RequestMethod.Equals("6")).Return("Get")
+ .End("Post")
+ }).ToListAsync();
}
- #endregion
-
- #region Post
-
- ///
- /// 新增.
- ///
- /// 请求参数.
- ///
- [HttpPost("")]
- public async Task Create_Api([FromBody] InterfaceOauthInput input)
- {
- if (await _repository.IsAnyAsync(x => (x.AppId == input.appId || x.AppName == input.appName) && x.DeleteMark == null))
- throw Oops.Oh(ErrorCode.D3001);
- var entity = input.Adapt();
- if (input.usefulLife.IsNullOrEmpty() || input.usefulLife == "0")
- {
- entity.UsefulLife = null;
- }
- var isOk = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
- if (isOk < 1)
- throw Oops.Oh(ErrorCode.COM1000);
- }
-
- ///
- /// 删除.
- ///
- /// 请求参数.
- ///
- [HttpDelete("{id}")]
- public async Task Delete(string id)
- {
- var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
- if (entity == null)
- throw Oops.Oh(ErrorCode.COM1005);
- var isOk = await _repository.AsUpdateable(entity).CallEntityMethod(m => m.Delete()).UpdateColumns(it => new { it.DeleteMark, it.DeleteTime, it.DeleteUserId }).ExecuteCommandHasChangeAsync();
- if (!isOk)
- throw Oops.Oh(ErrorCode.COM1002);
- }
-
- ///
- /// 修改.
- ///
- /// id.
- /// 请求参数.
- ///
- [HttpPut("{id}")]
- public async Task Update(string id, [FromBody] InterfaceOauthInput input)
- {
- if (await _repository.IsAnyAsync(x => x.Id != id && (x.AppId == input.appId || x.AppName == input.appName) && x.DeleteMark == null))
- throw Oops.Oh(ErrorCode.COM1004);
- var entity = input.Adapt();
- var isOk = await _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync();
- if (input.usefulLife.IsNullOrEmpty() || input.usefulLife == "0")
- {
- await _repository.AsUpdateable().SetColumns(it => new InterfaceOauthEntity()
- {
- UsefulLife = null
- }).Where(it => it.Id.Equals(id)).ExecuteCommandHasChangeAsync();
- }
- if (!isOk)
- throw Oops.Oh(ErrorCode.COM1001);
- }
-
- ///
- /// 授权接口.
- ///
- /// 请求参数.
- ///
- [HttpPost("saveInterfaceList")]
- public async Task SaveInterFaceList([FromBody] InterfaceOauthSaveInput input)
- {
- var isOk = await _repository.AsSugarClient().Updateable()
- .SetColumns(it => it.DataInterfaceIds == input.dataInterfaceIds).Where(x => x.Id == input.interfaceIdentId).ExecuteCommandHasChangeAsync();
- if (!isOk)
- throw Oops.Oh(ErrorCode.COM1002);
- }
- #endregion
+ return output;
}
+
+ ///
+ /// 列表.
+ ///
+ [HttpGet("")]
+ public async Task GetList([FromQuery] PageInputBase input)
+ {
+ var list = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == a.CreatorUserId))
+ .Where(a => a.DeleteMark == null)
+ .WhereIF(!string.IsNullOrEmpty(input.keyword), a => a.AppId.Contains(input.keyword) || a.AppName.Contains(input.keyword))
+ .OrderBy(a => a.SortCode).OrderBy(a => a.CreatorTime, OrderByType.Desc)
+ .Select((a, b) => new InterfaceOauthListOutput
+ {
+ id = a.Id,
+ lastModifyTime = a.LastModifyTime,
+ enabledMark = a.EnabledMark,
+ creatorUser = SqlFunc.MergeString(b.RealName, "/", b.Account),
+ appId = a.AppId,
+ appName = a.AppName,
+ usefulLife = a.UsefulLife,
+ sortCode = a.SortCode,
+ creatorTime = a.CreatorTime
+ }).ToPagedListAsync(input.currentPage, input.pageSize);
+ return PageResult.SqlSugarPageResult(list);
+ }
+
+ ///
+ /// 获取秘钥.
+ ///
+ ///
+ [HttpGet("getAppSecret")]
+ public async Task GetAppSecret()
+ {
+ return Guid.NewGuid().ToString().Replace("-", string.Empty);
+ }
+
+ ///
+ /// 日志.
+ ///
+ ///
+ ///
+ ///
+ [HttpGet("dataInterfaceLog/{id}")]
+ public async Task GetList(string id, [FromQuery] DataInterfaceLogListQuery input)
+ {
+ var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
+ var whereLambda = LinqExpression.And();
+ if (!input.startTime.IsNullOrEmpty() && !input.endTime.IsNullOrEmpty())
+ {
+ var startTime = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 00:00:00}", input.startTime?.TimeStampToDateTime()));
+ var endTime = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 23:59:59}", input.endTime?.TimeStampToDateTime()));
+ whereLambda = whereLambda.And(a => SqlFunc.Between(a.invokTime, startTime, endTime));
+ }
+ var list = await _repository.AsSugarClient().Queryable((a, b, c) =>
+ new JoinQueryInfos(JoinType.Left, b.Id == a.UserId, JoinType.Left, a.InvokId == c.Id))
+ .Where(a => a.OauthAppId == entity.AppId)
+ .WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.UserId.Contains(input.keyword) || a.InvokIp.Contains(input.keyword))
+ .Select((a, b, c) => new DataInterfaceLogListOutput
+ {
+ id = a.Id,
+ fullName = c.FullName,
+ enCode = c.EnCode,
+ invokDevice = a.InvokDevice,
+ invokIp = a.InvokIp,
+ userId = SqlFunc.MergeString(b.RealName, "/", b.Account),
+ invokTime = a.InvokTime,
+ invokType = a.InvokType,
+ invokWasteTime = a.InvokWasteTime
+ }).MergeTable().Where(whereLambda).OrderBy(a => a.invokTime).ToPagedListAsync(input.currentPage, input.pageSize);
+ return PageResult.SqlSugarPageResult(list);
+ }
+
+ #endregion
+
+ #region Post
+
+ ///
+ /// 新增.
+ ///
+ /// 请求参数.
+ ///
+ [HttpPost("")]
+ public async Task Create_Api([FromBody] InterfaceOauthInput input)
+ {
+ if (await _repository.IsAnyAsync(x => (x.AppId == input.appId || x.AppName == input.appName) && x.DeleteMark == null))
+ throw Oops.Oh(ErrorCode.D3001);
+ var entity = input.Adapt();
+ if (input.usefulLife.IsNullOrEmpty() || input.usefulLife == "0")
+ {
+ entity.UsefulLife = null;
+ }
+ var isOk = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
+ if (isOk < 1)
+ throw Oops.Oh(ErrorCode.COM1000);
+ }
+
+ ///
+ /// 删除.
+ ///
+ /// 请求参数.
+ ///
+ [HttpDelete("{id}")]
+ public async Task Delete(string id)
+ {
+ var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
+ if (entity == null)
+ throw Oops.Oh(ErrorCode.COM1005);
+ var isOk = await _repository.AsUpdateable(entity).CallEntityMethod(m => m.Delete()).UpdateColumns(it => new { it.DeleteMark, it.DeleteTime, it.DeleteUserId }).ExecuteCommandHasChangeAsync();
+ if (!isOk)
+ throw Oops.Oh(ErrorCode.COM1002);
+ }
+
+ ///
+ /// 修改.
+ ///
+ /// id.
+ /// 请求参数.
+ ///
+ [HttpPut("{id}")]
+ public async Task Update(string id, [FromBody] InterfaceOauthInput input)
+ {
+ if (await _repository.IsAnyAsync(x => x.Id != id && (x.AppId == input.appId || x.AppName == input.appName) && x.DeleteMark == null))
+ throw Oops.Oh(ErrorCode.COM1004);
+ var entity = input.Adapt();
+ var isOk = await _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync();
+ if (input.usefulLife.IsNullOrEmpty() || input.usefulLife == "0")
+ {
+ await _repository.AsUpdateable().SetColumns(it => new InterfaceOauthEntity()
+ {
+ UsefulLife = null
+ }).Where(it => it.Id.Equals(id)).ExecuteCommandHasChangeAsync();
+ }
+ if (!isOk)
+ throw Oops.Oh(ErrorCode.COM1001);
+ }
+
+ ///
+ /// 授权接口.
+ ///
+ /// 请求参数.
+ ///
+ [HttpPost("saveInterfaceList")]
+ public async Task SaveInterFaceList([FromBody] InterfaceOauthSaveInput input)
+ {
+ var isOk = await _repository.AsSugarClient().Updateable()
+ .SetColumns(it => it.DataInterfaceIds == input.dataInterfaceIds).Where(x => x.Id == input.interfaceIdentId).ExecuteCommandHasChangeAsync();
+ if (!isOk)
+ throw Oops.Oh(ErrorCode.COM1002);
+ }
+
+ #endregion
}
diff --git a/system/Tnb.Systems/System/MessageTemplateService.cs b/system/Tnb.Systems/System/MessageTemplateService.cs
index 7ff4fc30..0bd8ffea 100644
--- a/system/Tnb.Systems/System/MessageTemplateService.cs
+++ b/system/Tnb.Systems/System/MessageTemplateService.cs
@@ -375,7 +375,8 @@ public class MessageTemplateService : IMessageTemplateService, IDynamicApiContro
Account = sysconfig.emailAccount,
Password = sysconfig.emailPassword,
SMTPHost = sysconfig.emailSmtpHost,
- SMTPPort = sysconfig.emailSmtpPort.ParseToInt()
+ SMTPPort = sysconfig.emailSmtpPort.ParseToInt(),
+ Ssl = sysconfig.emailSsl,
}, mailModel);
}
diff --git a/system/Tnb.Systems/System/ModuleColumnService.cs b/system/Tnb.Systems/System/ModuleColumnService.cs
index 1ff7de3e..27d2a174 100644
--- a/system/Tnb.Systems/System/ModuleColumnService.cs
+++ b/system/Tnb.Systems/System/ModuleColumnService.cs
@@ -1,4 +1,5 @@
-using JNPF.Common.Core.Manager;
+using JNPF.Common.Const;
+using JNPF.Common.Core.Manager;
using JNPF.Common.Enums;
using JNPF.Common.Extension;
using JNPF.Common.Filter;
@@ -120,7 +121,7 @@ public class ModuleColumnService : IModuleColumnService, IDynamicApiController,
var visualDevId = moduleEntity.PropertyJson.ToObject()["moduleId"].ToString();
var visualDevEntity = await _repository.AsSugarClient().Queryable