Merge branch 'dev' of https://git.tuotong-tech.com/tnb/tnb.server into dev
This commit is contained in:
@@ -5,11 +5,11 @@ namespace Tnb.EquipMgr.Interfaces
|
|||||||
{
|
{
|
||||||
public interface IEqpEquipFileService
|
public interface IEqpEquipFileService
|
||||||
{
|
{
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// 上传附件
|
///// 上传附件
|
||||||
/// </summary>
|
///// </summary>
|
||||||
/// <param name="file"></param>
|
///// <param name="file"></param>
|
||||||
/// <returns></returns>
|
///// <returns></returns>
|
||||||
public Task<string> Upload(string equip_id,IFormFile file);
|
//public Task<string> Upload(string equip_id,IFormFile file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using JNPF.Common.Core.Manager;
|
using JNPF.Common.Core.Manager;
|
||||||
using JNPF.Common.Dtos.VisualDev;
|
using JNPF.Common.Dtos.VisualDev;
|
||||||
using JNPF.Common.Enums;
|
using JNPF.Common.Enums;
|
||||||
|
using JNPF.Common.Models;
|
||||||
using JNPF.DependencyInjection;
|
using JNPF.DependencyInjection;
|
||||||
using JNPF.DynamicApiController;
|
using JNPF.DynamicApiController;
|
||||||
using JNPF.FriendlyException;
|
using JNPF.FriendlyException;
|
||||||
@@ -10,6 +11,7 @@ using JNPF.Systems.Interfaces.Common;
|
|||||||
using JNPF.VisualDev;
|
using JNPF.VisualDev;
|
||||||
using JNPF.VisualDev.Entitys;
|
using JNPF.VisualDev.Entitys;
|
||||||
using JNPF.VisualDev.Interfaces;
|
using JNPF.VisualDev.Interfaces;
|
||||||
|
using Microsoft.AspNetCore.Components.Forms;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@@ -41,16 +43,16 @@ namespace Tnb.EquipMgr
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<string> Upload([FromForm]string equip_id,[FromForm]IFormFile file)
|
public async Task<string> Upload([FromForm]string equip_id,[FromForm] ChunkModel input)
|
||||||
{
|
{
|
||||||
string msg = "";
|
string msg = "";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var attachment = await _fileService.Uploader("annexpic", file);
|
var attachment = await _fileService.Uploader("annexpic", input);
|
||||||
|
|
||||||
EqpEquipFile eqpEquipFile = new EqpEquipFile()
|
EqpEquipFile eqpEquipFile = new EqpEquipFile()
|
||||||
{
|
{
|
||||||
file_name = file.FileName,
|
file_name = input.file.FileName,
|
||||||
equip_id = equip_id,
|
equip_id = equip_id,
|
||||||
create_id = _userManager.UserId,
|
create_id = _userManager.UserId,
|
||||||
create_time = DateTime.Now,
|
create_time = DateTime.Now,
|
||||||
|
|||||||
@@ -4,15 +4,88 @@
|
|||||||
//系统文件路径
|
//系统文件路径
|
||||||
"SystemPath": "D:\\ToTong\\tnb\\Resources",
|
"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
|
"PreviewType": "kkfile", //文件预览方式 (kkfile,yozo)默认使用kkfile
|
||||||
"KKFileDomain": "http://127.0.0.1:30090/FileServer",
|
"KKFileDomain": "http://127.0.0.1:30090/FileServer",
|
||||||
"Domain": "http://yinmai.tpddns.cn:7772",
|
"Domain": "http://yinmai.tpddns.cn:7772",
|
||||||
@@ -21,18 +94,52 @@
|
|||||||
"domainKey": "57462250284462899305150",
|
"domainKey": "57462250284462899305150",
|
||||||
"UploadAPI": "http://dmc.yozocloud.cn/api/file/http?fileUrl={0}&appId={1}&sign={2}", //上传接口
|
"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}", //预览接口
|
"DownloadAPI": "http://eic.yozocloud.cn/api/view/file?fileVersionId={0}&appId={1}&sign={2}", //预览接口
|
||||||
"AppId": "yozoAQh5dPSt6063", //应用Id
|
"AppId": "yozoAQh5dPSt6063", // 应用Id
|
||||||
"AppKey": "6365bfbd733fce644fd7ac0aaeca" //签名
|
"AppKey": "6365bfbd733fce644fd7ac0aaeca" // 签名
|
||||||
},
|
},
|
||||||
//================== 系统错误邮件报告反馈相关 ============================== -->
|
// ================== 系统错误邮件报告反馈相关 ============================== -->
|
||||||
//软件的错误报告
|
// 软件的错误报告
|
||||||
"ErrorReport": false,
|
"ErrorReport": false,
|
||||||
//软件的错误报告发给谁
|
//软件的错误报告发给谁
|
||||||
"ErrorReportTo": "tuotong_tech@163.com"
|
"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": {
|
"Socials": {
|
||||||
"SocialsEnabled": true,
|
"SocialsEnabled": false,
|
||||||
"DoMain": "https://562f45p309.goho.co/dev", // 外网能访问的地址(域名), 回调的时候拼接接口地址用
|
"DoMain": "https://562f45p309.goho.co/dev", // 外网能访问的地址(域名), 回调的时候拼接接口地址用
|
||||||
"Config": [
|
"Config": [
|
||||||
{
|
{
|
||||||
@@ -76,8 +183,9 @@
|
|||||||
},
|
},
|
||||||
//================== 消息跳转配置 ============================== -->
|
//================== 消息跳转配置 ============================== -->
|
||||||
"Message": {
|
"Message": {
|
||||||
"DoMainPc": "http://127.0.0.1:3000", // 前端PC外网能访问的地址(域名), 回调的时候拼接接口地址用
|
"ApiDoMain": "http://localhost:5000", // 后端Api路径 (发布时与DoMainPc一致)
|
||||||
"DoMainApp": "http://127.0.0.1:3000", // 前端App外网能访问的地址(域名), 回调的时候拼接接口地址用
|
"DoMainPc": "http://localhost:3000", // 前端PC外网能访问的地址(域名), 回调的时候拼接接口地址用
|
||||||
|
"DoMainApp": "http://localhost:8081", // 前端App外网能访问的地址(域名), 回调的时候拼接接口地址用
|
||||||
"AppPushUrl": "https://8e84eea8-6922-4033-8e86-67ad7442e692.bspapp.com/unipush"
|
"AppPushUrl": "https://8e84eea8-6922-4033-8e86-67ad7442e692.bspapp.com/unipush"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
8
apihost/Tnb.API.Entry/Configurations/EventBus.json
Normal file
8
apihost/Tnb.API.Entry/Configurations/EventBus.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"EventBus": {
|
||||||
|
"EventBusType": "Memory", //Memory,RabbitMQ
|
||||||
|
"HostName": "192.168.0.232",
|
||||||
|
"UserName": "jnpf",
|
||||||
|
"Password": "jnpf@2019"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"JWTSettings": {
|
"JWTSettings": {
|
||||||
"ValidateIssuerSigningKey": true, // 是否验证密钥,bool 类型,默认true
|
"ValidateIssuerSigningKey": true, // 是否验证密钥,bool 类型,默认true
|
||||||
"IssuerSigningKey": "7k5yOxSMHVdYjs61gkgUY3W9DHbgk7tokaZlP3QIlfk34D1H7jYEOcLybClW1aKl", // 密钥,string 类型,必须是复杂密钥,长度大于16
|
"IssuerSigningKey": "RkayGi4ltkMWrSQKsQTWic1VnakqsQfaJOmJIBUWE1gxGaS0IrJHxa9anjVAwuew", // 密钥,string 类型,必须是复杂密钥,长度大于16
|
||||||
"ValidateIssuer": true, // 是否验证签发方,bool 类型,默认true
|
"ValidateIssuer": true, // 是否验证签发方,bool 类型,默认true
|
||||||
"ValidIssuer": "tuotong", // 签发方,string 类型
|
"ValidIssuer": "tuotong", // 签发方,string 类型
|
||||||
"ValidateAudience": true, // 是否验证签收方,bool 类型,默认true
|
"ValidateAudience": true, // 是否验证签收方,bool 类型,默认true
|
||||||
|
|||||||
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
"Group": "Default",
|
"Group": "Default",
|
||||||
"Title": "ToTong Next Builder",
|
"Title": "ToTong Next Builder",
|
||||||
"Description": "",
|
"Description": "",
|
||||||
"Version": "3.4.5"
|
"Version": "3.4.6"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"LoginInfo": {
|
"LoginInfo": {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using JNPF;
|
using JNPF;
|
||||||
|
using JNPF.Common.Core;
|
||||||
using JNPF.Common.Options;
|
using JNPF.Common.Options;
|
||||||
using JNPF.EventHandler;
|
using JNPF.EventHandler;
|
||||||
using OnceMi.AspNetCore.OSS;
|
using OnceMi.AspNetCore.OSS;
|
||||||
@@ -17,40 +18,53 @@ public static class ConfigureEventBusExtensions
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IServiceCollection ConfigureEventBus(this IServiceCollection services)
|
public static IServiceCollection ConfigureEventBus(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
// 注册EventBus服务
|
// 注册EventBus服务
|
||||||
services.AddEventBus(options =>
|
// 注册EventBus服务
|
||||||
{
|
services.AddEventBus(options =>
|
||||||
//// 创建连接工厂
|
{
|
||||||
//var factory = new RabbitMQ.Client.ConnectionFactory
|
var config = App.GetOptions<EventBusOptions>();
|
||||||
//{
|
|
||||||
// // 设置主机名
|
|
||||||
// HostName = "192.168.0.232",
|
|
||||||
|
|
||||||
// // 用户名
|
if (config.EventBusType != EventBusType.Memory)
|
||||||
// UserName = "jnpf",
|
{
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
//// 替换默认事件总线存储器
|
// 创建默认内存通道事件源对象,可自定义队列路由key,比如这里是 eventbus
|
||||||
//options.ReplaceStorer(serviceProvider =>
|
var rbmqEventSourceStorer = new RabbitMQEventSourceStorer(factory, "eventbus", 3000);
|
||||||
//{
|
|
||||||
// return rbmqEventSourceStorer;
|
|
||||||
//});
|
|
||||||
|
|
||||||
options.UseUtcTimestamp = false;
|
// 替换默认事件总线存储器
|
||||||
|
options.ReplaceStorer(serviceProvider =>
|
||||||
|
{
|
||||||
|
return rbmqEventSourceStorer;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 不启用事件日志
|
options.UseUtcTimestamp = false;
|
||||||
options.LogEnabled = false;
|
|
||||||
|
|
||||||
// 事件执行器(失败重试)
|
// 不启用事件日志
|
||||||
options.AddExecutor<RetryEventHandlerExecutor>();
|
options.LogEnabled = false;
|
||||||
});
|
|
||||||
|
|
||||||
return services;
|
// 事件执行器(失败重试)
|
||||||
|
options.AddExecutor<RetryEventHandlerExecutor>();
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddConfigurableOptions<EventBusOptions>();
|
||||||
|
|
||||||
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@ using Newtonsoft.Json;
|
|||||||
using OnceMi.AspNetCore.OSS;
|
using OnceMi.AspNetCore.OSS;
|
||||||
using JNPF.API.Entry.Handlers;
|
using JNPF.API.Entry.Handlers;
|
||||||
using JNPF.Common.Cache;
|
using JNPF.Common.Cache;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
|
||||||
namespace Microsoft.Extensions.DependencyInjection;
|
namespace Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
@@ -18,60 +19,108 @@ namespace Microsoft.Extensions.DependencyInjection;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ConfigureMvcControllerExtensions
|
public static class ConfigureMvcControllerExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// OSS服务配置.
|
/// OSS服务配置.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="services"></param>
|
/// <param name="services"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IServiceCollection ConfigureMvcController(this IServiceCollection services)
|
public static IServiceCollection ConfigureMvcController(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddControllers()
|
services.AddControllers()
|
||||||
.AddMvcFilter<RequestActionFilter>()
|
.AddMvcFilter<RequestActionFilter>()
|
||||||
.AddInjectWithUnifyResult<RESTfulResultProvider>()
|
.AddInjectWithUnifyResult<RESTfulResultProvider>()
|
||||||
.AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null)
|
.AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null)
|
||||||
.AddNewtonsoftJson(options =>
|
.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
|
// 设置时区为 UTC
|
||||||
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
|
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
|
||||||
|
|
||||||
// 格式化json输出的日期格式
|
// 格式化json输出的日期格式
|
||||||
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
|
DateFormatString = "yyyy-MM-dd HH:mm:ss",
|
||||||
|
|
||||||
// 忽略空值
|
|
||||||
// options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
|
|
||||||
|
|
||||||
// 忽略循环引用
|
|
||||||
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
|
|
||||||
|
|
||||||
// 格式化json输出的日期格式为时间戳
|
|
||||||
options.SerializerSettings.Converters.Add(new NewtonsoftDateTimeJsonConverter());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 配置Nginx转发获取客户端真实IP
|
// 配置Nginx转发获取客户端真实IP
|
||||||
// 注1:如果负载均衡不是在本机通过 Loopback 地址转发请求的,一定要加上options.KnownNetworks.Clear()和options.KnownProxies.Clear()
|
// 注1:如果负载均衡不是在本机通过 Loopback 地址转发请求的,一定要加上options.KnownNetworks.Clear()和options.KnownProxies.Clear()
|
||||||
// 注2:如果设置环境变量 ASPNETCORE_FORWARDEDHEADERS_ENABLED 为 True,则不需要下面的配置代码
|
// 注2:如果设置环境变量 ASPNETCORE_FORWARDEDHEADERS_ENABLED 为 True,则不需要下面的配置代码
|
||||||
services.Configure<ForwardedHeadersOptions>(options =>
|
services.Configure<ForwardedHeadersOptions>(options =>
|
||||||
{
|
{
|
||||||
options.ForwardedHeaders = ForwardedHeaders.All;
|
options.ForwardedHeaders = ForwardedHeaders.All;
|
||||||
options.KnownNetworks.Clear();
|
options.KnownNetworks.Clear();
|
||||||
options.KnownProxies.Clear();
|
options.KnownProxies.Clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Jwt处理程序
|
// Jwt处理程序
|
||||||
services.AddJwt<JwtHandler>(enableGlobalAuthorize: true);
|
services.AddJwt<JwtHandler>(enableGlobalAuthorize: true, jwtBearerConfigure: options =>
|
||||||
|
{
|
||||||
|
// 实现 JWT 身份验证过程控制
|
||||||
|
options.Events = new JwtBearerEvents
|
||||||
|
{
|
||||||
|
// 添加读取 Token 的方式
|
||||||
|
OnMessageReceived = context =>
|
||||||
|
{
|
||||||
|
var httpContext = context.HttpContext;
|
||||||
|
|
||||||
// 跨域
|
// 判断请求是否包含 token 参数,如果有就设置给 Token
|
||||||
services.AddCorsAccessor();
|
if (httpContext.Request.Query.ContainsKey("token"))
|
||||||
|
{
|
||||||
|
// 设置 Token
|
||||||
|
context.Token = httpContext.Request.Query["token"];
|
||||||
|
}
|
||||||
|
|
||||||
services.AddConfigurableOptions<CacheOptions>();
|
return Task.CompletedTask;
|
||||||
services.AddSession();
|
},
|
||||||
services.AddMemoryCache(); // 使用本地缓存必须添加
|
|
||||||
|
|
||||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
// Token 验证通过处理
|
||||||
|
OnTokenValidated = context =>
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
return services;
|
// 跨域
|
||||||
}
|
services.AddCorsAccessor();
|
||||||
|
|
||||||
|
// 注册远程请求
|
||||||
|
services.AddRemoteRequest();
|
||||||
|
|
||||||
|
// 视图引擎
|
||||||
|
services.AddViewEngine();
|
||||||
|
|
||||||
|
// 脱敏词汇检测
|
||||||
|
services.AddSensitiveDetection();
|
||||||
|
|
||||||
|
// WebSocket服务
|
||||||
|
services.AddWebSocketManager();
|
||||||
|
|
||||||
|
services.AddSession();
|
||||||
|
|
||||||
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ public static class ConfigureSqlSugarExtensions
|
|||||||
// 默认数据库
|
// 默认数据库
|
||||||
connectConfigList.Add(new ConnectionConfig
|
connectConfigList.Add(new ConnectionConfig
|
||||||
{
|
{
|
||||||
ConnectionString = string.Format(conn.DefaultConnection, conn.Host, conn.Port, conn.DBName, conn.UserName, conn.Password),
|
ConnectionString = conn.ConnectString,
|
||||||
DbType = DBType,
|
DbType = DBType,
|
||||||
IsAutoCloseConnection = true,
|
IsAutoCloseConnection = true,
|
||||||
ConfigId = conn.ConfigId,
|
ConfigId = conn.ConfigId,
|
||||||
@@ -62,10 +62,9 @@ public static class ConfigureSqlSugarExtensions
|
|||||||
//};
|
//};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
services.AddUnitOfWork<SqlSugarUnitOfWork>();
|
||||||
services.AddConfigurableOptions<ConnectionStringsOptions>();
|
services.AddConfigurableOptions<ConnectionStringsOptions>();
|
||||||
services.AddConfigurableOptions<TenantOptions>();
|
services.AddConfigurableOptions<TenantOptions>();
|
||||||
services.AddUnitOfWork<SqlSugarUnitOfWork>();
|
|
||||||
|
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,15 +7,15 @@ public class WebComponent : IWebComponent
|
|||||||
{
|
{
|
||||||
public void Load(WebApplicationBuilder builder, ComponentContext componentContext)
|
public void Load(WebApplicationBuilder builder, ComponentContext componentContext)
|
||||||
{
|
{
|
||||||
//// <20><>־<EFBFBD><D6BE><EFBFBD><EFBFBD>
|
builder.Host.UseWindowsService();
|
||||||
|
//// 日志过滤
|
||||||
//builder.Logging.AddFilter((provider, category, logLevel) =>
|
//builder.Logging.AddFilter((provider, category, logLevel) =>
|
||||||
//{
|
//{
|
||||||
// return !new[] { "Microsoft.Hosting", "Microsoft.AspNetCore" }.Any(u => category.StartsWith(u)) && logLevel >= LogLevel.Information;
|
// return !new[] { "Microsoft.Hosting", "Microsoft.AspNetCore" }.Any(u => category.StartsWith(u)) && logLevel >= LogLevel.Information;
|
||||||
//});
|
//});
|
||||||
builder.Host.UseWindowsService();
|
|
||||||
builder.WebHost.ConfigureKestrel(options =>
|
builder.WebHost.ConfigureKestrel(options =>
|
||||||
{
|
{
|
||||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> null
|
// 长度最好不要设置 null
|
||||||
options.Limits.MaxRequestBodySize = 52428800;
|
options.Limits.MaxRequestBodySize = 52428800;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using IGeekFan.AspNetCore.Knife4jUI;
|
using IGeekFan.AspNetCore.Knife4jUI;
|
||||||
using JNPF.API.Entry.Handlers;
|
using JNPF.API.Entry.Handlers;
|
||||||
using JNPF.Common.Cache;
|
using JNPF.Common.Cache;
|
||||||
|
using JNPF.Common.Core;
|
||||||
using JNPF.Common.Core.Filter;
|
using JNPF.Common.Core.Filter;
|
||||||
using JNPF.Common.Core.Handlers;
|
using JNPF.Common.Core.Handlers;
|
||||||
using JNPF.Common.Security;
|
using JNPF.Common.Security;
|
||||||
@@ -26,87 +27,88 @@ namespace JNPF.API.Entry;
|
|||||||
|
|
||||||
public class Startup : AppStartup
|
public class Startup : AppStartup
|
||||||
{
|
{
|
||||||
public void ConfigureServices(IServiceCollection services)
|
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> senparcSetting, IOptions<SenparcWeixinSetting> 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 =>
|
|
||||||
{
|
{
|
||||||
options.RoutePrefix = "newapi"; // 配置 Knife4UI 路由地址,现在是 /newapi
|
// 注册和配置Mvc和api服务
|
||||||
foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())
|
services.ConfigureMvcController();
|
||||||
{
|
|
||||||
options.SwaggerEndpoint("/" + groupInfo.RouteTemplate, groupInfo.Title);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.UseInject(string.Empty);
|
// 注册和配置SqlSugar
|
||||||
|
services.ConfigureSqlSugar();
|
||||||
|
|
||||||
//app.MapWebSocketManager("/api/message/websocket", serviceProvider.GetService<IMHandler>());
|
// 注册EventBus服务
|
||||||
app.MapWebSocketManager("/websocket", serviceProvider.GetRequiredService<IMHandler>());
|
services.ConfigureEventBus();
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
// 注册和配置日志服务
|
||||||
|
services.ConfigureLogging();
|
||||||
|
|
||||||
|
// 注册和配置存储服务
|
||||||
|
services.ConfigureOSSService();
|
||||||
|
|
||||||
|
// 任务调度
|
||||||
|
//services.AddSchedule(options =>
|
||||||
|
//{
|
||||||
|
// options.AddPersistence<DbJobPersistence>();
|
||||||
|
//});
|
||||||
|
|
||||||
|
// 任务调度
|
||||||
|
services.AddTaskScheduler();
|
||||||
|
|
||||||
|
services.AddMemoryCache(); // 使用本地缓存必须添加
|
||||||
|
services.AddConfigurableOptions<CacheOptions>();
|
||||||
|
|
||||||
|
// 微信
|
||||||
|
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> senparcSetting, IOptions<SenparcWeixinSetting> senparcWeixinSetting)
|
||||||
{
|
{
|
||||||
endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
|
// 添加状态码拦截中间件
|
||||||
});
|
app.UseUnifyResultStatusCodes();
|
||||||
|
|
||||||
SnowflakeIdHelper.InitYitIdWorker();
|
// app.UseHttpsRedirection(); // 强制https
|
||||||
|
app.UseStaticFiles();
|
||||||
|
|
||||||
//serviceProvider.GetRequiredService<ITimeTaskService>().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<IMHandler>());
|
||||||
|
app.MapWebSocketManager("/websocket", serviceProvider.GetRequiredService<IMHandler>());
|
||||||
|
|
||||||
|
app.UseEndpoints(endpoints =>
|
||||||
|
{
|
||||||
|
endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||||
|
});
|
||||||
|
|
||||||
|
SnowflakeIdHelper.InitYitIdWorker();
|
||||||
|
|
||||||
|
//serviceProvider.GetRequiredService<ITimeTaskService>().StartTimerJob();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ public static class EnumExtensions
|
|||||||
{
|
{
|
||||||
if (field.FieldType.IsEnum)
|
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);
|
object[] arr = field.GetCustomAttributes(typeDescription, true);
|
||||||
if (arr.Length > 0)
|
if (arr.Length > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AlipaySDKNet.Standard" Version="4.6.442" />
|
<PackageReference Include="AlipaySDKNet.Standard" Version="4.6.442" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.0" />
|
||||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
|
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
|
||||||
<PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" />
|
<PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" />
|
||||||
|
|||||||
55
common/Tnb.Common.Core/EventBus/EventBusOptions.cs
Normal file
55
common/Tnb.Common.Core/EventBus/EventBusOptions.cs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
using JNPF.ConfigurableOptions;
|
||||||
|
|
||||||
|
namespace JNPF.Common.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 事件总线配置.
|
||||||
|
/// </summary>
|
||||||
|
public class EventBusOptions : IConfigurableOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 事件总线类型.
|
||||||
|
/// </summary>
|
||||||
|
public EventBusType EventBusType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 服务器地址.
|
||||||
|
/// </summary>
|
||||||
|
public string HostName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账号.
|
||||||
|
/// </summary>
|
||||||
|
public string UserName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 密码.
|
||||||
|
/// </summary>
|
||||||
|
public string Password { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 事件总线自定义事件源存储器类型.
|
||||||
|
/// </summary>
|
||||||
|
public enum EventBusType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 内存.
|
||||||
|
/// </summary>
|
||||||
|
Memory,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RabbitMQ.
|
||||||
|
/// </summary>
|
||||||
|
RabbitMQ,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Redis.
|
||||||
|
/// </summary>
|
||||||
|
Redis,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Kafka.
|
||||||
|
/// </summary>
|
||||||
|
Kafka,
|
||||||
|
}
|
||||||
@@ -42,7 +42,7 @@ public class LogEventSubscriber : IEventSubscriber, ISingleton
|
|||||||
_sqlSugarClient.ChangeDatabase(log.ConnectionConfig.ConfigId);
|
_sqlSugarClient.ChangeDatabase(log.ConnectionConfig.ConfigId);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _sqlSugarClient.Insertable(log.Entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync();
|
await _sqlSugarClient.CopyNew().Insertable(log.Entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -61,6 +61,6 @@ public class LogEventSubscriber : IEventSubscriber, ISingleton
|
|||||||
_sqlSugarClient.ChangeDatabase(log.ConnectionConfig.ConfigId);
|
_sqlSugarClient.ChangeDatabase(log.ConnectionConfig.ConfigId);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _sqlSugarClient.Insertable(log.Entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync();
|
await _sqlSugarClient.CopyNew().Insertable(log.Entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
using JNPF.Systems.Entitys.System;
|
using JNPF.EventBus;
|
||||||
using JNPF.EventBus;
|
using JNPF.TaskScheduler.Entitys;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
|
||||||
namespace JNPF.EventHandler;
|
namespace JNPF.EventHandler;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using JNPF.Systems.Entitys.System;
|
using JNPF.EventBus;
|
||||||
using JNPF.EventBus;
|
using JNPF.TaskScheduler.Entitys;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
|
||||||
namespace JNPF.EventHandler;
|
namespace JNPF.EventHandler;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using JNPF.Common.Security;
|
using JNPF.Common.Extension;
|
||||||
|
using JNPF.Common.Security;
|
||||||
using JNPF.EventBus;
|
using JNPF.EventBus;
|
||||||
using JNPF.Logging;
|
using JNPF.Logging;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
@@ -59,8 +60,6 @@ public sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable
|
|||||||
// 创建通道
|
// 创建通道
|
||||||
_model = _connection.CreateModel();
|
_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);
|
_model.QueueDeclare(queue: routeKey, durable: false, exclusive: false, autoDelete: false, arguments: null);
|
||||||
|
|
||||||
// 将MaxKey 交换机绑定到 路由中
|
// 将MaxKey 交换机绑定到 路由中
|
||||||
_model.QueueBind(queue: routeKey, exchange: ExchangeName, routingKey: "#");
|
// _model.QueueBind(queue: routeKey, exchange: "MXK_IDENTITY_MAIN_TOPIC", routingKey: "#");
|
||||||
|
|
||||||
// 字节限制,一次接收的消息数,全局/
|
// 字节限制,一次接收的消息数,全局/
|
||||||
// 据说prefetchSize 和global这两项,rabbitmq没有实现,暂且不研究
|
// 据说prefetchSize 和global这两项,rabbitmq没有实现,暂且不研究
|
||||||
@@ -95,6 +94,9 @@ public sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable
|
|||||||
// 转换为 IEventSource,这里可以选择自己喜欢的序列化工具,如果自定义了 EventSource,注意属性是可读可写
|
// 转换为 IEventSource,这里可以选择自己喜欢的序列化工具,如果自定义了 EventSource,注意属性是可读可写
|
||||||
var eventSource = JsonSerializer.Deserialize<ChannelEventSource>(stringEventSource);
|
var eventSource = JsonSerializer.Deserialize<ChannelEventSource>(stringEventSource);
|
||||||
|
|
||||||
|
// 判断到是单点登录服务端信息
|
||||||
|
if (eventSource.EventId.IsNullOrEmpty()) eventSource = new ChannelEventSource("User:Maxkey_Identity", stringEventSource);
|
||||||
|
|
||||||
Log.Information($"- 接收到消息:{eventSource.ToJsonString()}");
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -122,7 +124,7 @@ public sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable
|
|||||||
throw new ArgumentNullException(nameof(eventSource));
|
throw new ArgumentNullException(nameof(eventSource));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 这里判断是否是 ChannelEventSource 或者 自定义的 EventSouce
|
// 这里判断是否是 ChannelEventSource 或者 自定义的 EventSource
|
||||||
if (eventSource is ChannelEventSource source)
|
if (eventSource is ChannelEventSource source)
|
||||||
{
|
{
|
||||||
// 序列化,这里可以选择自己喜欢的序列化工具
|
// 序列化,这里可以选择自己喜欢的序列化工具
|
||||||
@@ -146,7 +148,8 @@ public sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable
|
|||||||
public async ValueTask<IEventSource> ReadAsync(CancellationToken cancellationToken)
|
public async ValueTask<IEventSource> ReadAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// 读取一条事件源
|
// 读取一条事件源
|
||||||
return await _channel.Reader.ReadAsync(cancellationToken);
|
var eventSource = await _channel.Reader.ReadAsync(cancellationToken);
|
||||||
|
return eventSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using JNPF.Common.Configuration;
|
using JNPF.Common.Configuration;
|
||||||
using JNPF.DependencyInjection;
|
using JNPF.DependencyInjection;
|
||||||
using JNPF.EventBus;
|
using JNPF.EventBus;
|
||||||
using JNPF.Systems.Entitys.System;
|
using JNPF.TaskScheduler.Entitys;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
|
||||||
namespace JNPF.EventHandler;
|
namespace JNPF.EventHandler;
|
||||||
@@ -40,7 +40,7 @@ public class TaskEventSubscriber : IEventSubscriber, ISingleton
|
|||||||
_sqlSugarClient.ChangeDatabase(log.ConnectionConfig.ConfigId);
|
_sqlSugarClient.ChangeDatabase(log.ConnectionConfig.ConfigId);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _sqlSugarClient.Updateable<TimeTaskEntity>().SetColumns(x => new TimeTaskEntity()
|
await _sqlSugarClient.CopyNew().Updateable<TimeTaskEntity>().SetColumns(x => new TimeTaskEntity()
|
||||||
{
|
{
|
||||||
RunCount = x.RunCount + 1,
|
RunCount = x.RunCount + 1,
|
||||||
LastRunTime = DateTime.Now,
|
LastRunTime = DateTime.Now,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using JNPF.Common.Configuration;
|
using JNPF.Common.Configuration;
|
||||||
using JNPF.DependencyInjection;
|
using JNPF.DependencyInjection;
|
||||||
using JNPF.EventBus;
|
using JNPF.EventBus;
|
||||||
|
using JNPF.Systems.Interfaces.Permission;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
|
||||||
namespace JNPF.EventHandler;
|
namespace JNPF.EventHandler;
|
||||||
@@ -15,12 +16,20 @@ public class UserEventSubscriber : IEventSubscriber, ISingleton
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static SqlSugarScope? _sqlSugarClient;
|
private static SqlSugarScope? _sqlSugarClient;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户服务.
|
||||||
|
/// </summary>
|
||||||
|
private readonly IUsersService _usersService;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造函数.
|
/// 构造函数.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public UserEventSubscriber(ISqlSugarClient context)
|
public UserEventSubscriber(
|
||||||
|
ISqlSugarClient context,
|
||||||
|
IUsersService usersService)
|
||||||
{
|
{
|
||||||
_sqlSugarClient = (SqlSugarScope)context;
|
_sqlSugarClient = (SqlSugarScope)context;
|
||||||
|
_usersService = usersService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -39,7 +48,7 @@ public class UserEventSubscriber : IEventSubscriber, ISingleton
|
|||||||
_sqlSugarClient.ChangeDatabase(log.ConnectionConfig.ConfigId);
|
_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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -47,9 +56,10 @@ public class UserEventSubscriber : IEventSubscriber, ISingleton
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[EventSubscribe("User:maxkey_identity")]
|
[EventSubscribe("User:Maxkey_Identity")]
|
||||||
public async Task ReceiveUserInfo(EventHandlerExecutingContext context)
|
public async Task ReceiveUserInfo(EventHandlerExecutingContext context)
|
||||||
{
|
{
|
||||||
var log = (UserEventSource)context.Source;
|
var log = context.Source.Payload;
|
||||||
|
await _usersService.Receive(log.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,6 @@ using Microsoft.AspNetCore.Mvc.Filters;
|
|||||||
using JNPF.Systems.Entitys.System;
|
using JNPF.Systems.Entitys.System;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using MimeKit;
|
|
||||||
|
|
||||||
namespace JNPF.Common.Core.Filter;
|
namespace JNPF.Common.Core.Filter;
|
||||||
|
|
||||||
@@ -21,58 +20,57 @@ namespace JNPF.Common.Core.Filter;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class LogExceptionHandler : IGlobalExceptionHandler, ISingleton
|
public class LogExceptionHandler : IGlobalExceptionHandler, ISingleton
|
||||||
{
|
{
|
||||||
private readonly IEventPublisher _eventPublisher;
|
private readonly IEventPublisher _eventPublisher;
|
||||||
|
|
||||||
public LogExceptionHandler(IEventPublisher eventPublisher)
|
public LogExceptionHandler(IEventPublisher eventPublisher)
|
||||||
{
|
|
||||||
_eventPublisher = eventPublisher;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 异步写入异常日记.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
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<ConnectionConfigOptions>();
|
_eventPublisher = eventPublisher;
|
||||||
string userId = userContext?.FindFirstValue(ClaimConst.CLAINMUSERID);
|
}
|
||||||
string userName = userContext?.FindFirstValue(ClaimConst.CLAINMREALNAME);
|
|
||||||
|
/// <summary>
|
||||||
if (!App.HttpContext.Request.Headers.ContainsKey("Authorization"))
|
/// 异步写入异常日记.
|
||||||
{
|
/// </summary>
|
||||||
var bearer = App.HttpContext.Request.QueryString.Value.Matches(@"[?&]token=Bearer%20([\w\.-]+)($|&)");
|
/// <param name="context"></param>
|
||||||
if (bearer.Count() > 0)
|
/// <returns></returns>
|
||||||
{
|
public async Task OnExceptionAsync(ExceptionContext context)
|
||||||
string token = bearer.Last();
|
{
|
||||||
IEnumerable<Claim> claims = JWTEncryption.ReadJwtToken(token.Replace("Bearer ", string.Empty).Replace("bearer ", string.Empty))?.Claims;
|
var userContext = App.User;
|
||||||
options = claims.FirstOrDefault(e => e.Type == ClaimConst.CONNECTIONCONFIG).ToObject<ConnectionConfigOptions>();
|
var httpContext = context.HttpContext;
|
||||||
userId = claims.FirstOrDefault(e => e.Type == ClaimConst.CLAINMUSERID)?.Value;
|
var httpRequest = httpContext?.Request;
|
||||||
userName = claims.FirstOrDefault(e => e.Type == ClaimConst.CLAINMREALNAME)?.Value;
|
var headers = httpRequest?.Headers;
|
||||||
}
|
UserAgent userAgent = new UserAgent(httpContext);
|
||||||
}
|
|
||||||
|
if (!context.ActionDescriptor.EndpointMetadata.Any(m => m.GetType() == typeof(IgnoreLogAttribute)))
|
||||||
await _eventPublisher.PublishAsync(new LogEventSource("Log:CreateExLog", options, new SysLogEntity
|
{
|
||||||
{
|
ConnectionConfigOptions options = userContext?.FindFirstValue(ClaimConst.CONNECTIONCONFIG)?.ToObject<ConnectionConfigOptions>();
|
||||||
Id = SnowflakeIdHelper.NextId(),
|
string userId = userContext?.FindFirstValue(ClaimConst.CLAINMUSERID);
|
||||||
UserId = userId,
|
string userName = userContext?.FindFirstValue(ClaimConst.CLAINMREALNAME);
|
||||||
UserName = userName,
|
|
||||||
Category = 4,
|
if (!App.HttpContext.Request.Headers.ContainsKey("Authorization"))
|
||||||
IPAddress = NetHelper.Ip,
|
{
|
||||||
RequestURL = httpRequest.Path,
|
string token = App.HttpContext.Request.QueryString.Value.Matches(@"[?&]token=Bearer%20([\w\.-]+)($|&)").LastOrDefault();
|
||||||
RequestMethod = httpRequest.Method,
|
if (!string.IsNullOrEmpty(token))
|
||||||
Json = context.Exception.Message + "\n" + context.Exception.StackTrace + "\n" + context.Exception.TargetSite.GetParameters().ToString(),
|
{
|
||||||
PlatForm = string.Format("{0}-{1}", userAgent.OS.ToString(), userAgent.RawValue),
|
IEnumerable<Claim> claims = JWTEncryption.ReadJwtToken(token.Replace("Bearer ", string.Empty).Replace("bearer ", string.Empty))?.Claims;
|
||||||
CreatorTime = DateTime.Now
|
options = claims.FirstOrDefault(e => e.Type == ClaimConst.CONNECTIONCONFIG).ToObject<ConnectionConfigOptions>();
|
||||||
}));
|
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
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -22,93 +22,92 @@ namespace JNPF.Common.Core.Filter;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class RequestActionFilter : IAsyncActionFilter
|
public class RequestActionFilter : IAsyncActionFilter
|
||||||
{
|
{
|
||||||
private readonly IEventPublisher _eventPublisher;
|
private readonly IEventPublisher _eventPublisher;
|
||||||
|
|
||||||
public RequestActionFilter(IEventPublisher eventPublisher)
|
public RequestActionFilter(IEventPublisher eventPublisher)
|
||||||
{
|
|
||||||
_eventPublisher = eventPublisher;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 请求日记写入.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context"></param>
|
|
||||||
/// <param name="next"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
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);
|
_eventPublisher = eventPublisher;
|
||||||
ConnectionConfigOptions options = userContext?.FindFirstValue(ClaimConst.CONNECTIONCONFIG)?.ToObject<ConnectionConfigOptions>();
|
}
|
||||||
var userId = userContext?.FindFirstValue(ClaimConst.CLAINMUSERID);
|
|
||||||
var userName = userContext?.FindFirstValue(ClaimConst.CLAINMREALNAME);
|
/// <summary>
|
||||||
if (!App.HttpContext.Request.Headers.ContainsKey("Authorization"))
|
/// 请求日记写入.
|
||||||
{
|
/// </summary>
|
||||||
var bearer = App.HttpContext.Request.QueryString.Value.Matches(@"[?&]token=Bearer%20([\w\.-]+)($|&)");
|
/// <param name="context"></param>
|
||||||
if (bearer.Count() > 0)
|
/// <param name="next"></param>
|
||||||
{
|
/// <returns></returns>
|
||||||
string token = bearer.Last();
|
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||||
IEnumerable<Claim> claims = JWTEncryption.ReadJwtToken(token.Replace("Bearer ", string.Empty).Replace("bearer ", string.Empty))?.Claims;
|
{
|
||||||
options = claims.FirstOrDefault(e => e.Type == ClaimConst.CONNECTIONCONFIG).ToObject<ConnectionConfigOptions>();
|
var userContext = App.User;
|
||||||
userId = claims.FirstOrDefault(e => e.Type == ClaimConst.CLAINMUSERID)?.Value;
|
var httpContext = context.HttpContext;
|
||||||
userName = claims.FirstOrDefault(e => e.Type == ClaimConst.CLAINMREALNAME)?.Value;
|
var httpRequest = httpContext.Request;
|
||||||
}
|
UserAgent userAgent = new UserAgent(httpContext);
|
||||||
}
|
var actionDes = (ControllerActionDescriptor)context.ActionDescriptor;
|
||||||
|
var actionName = $"{actionDes.ControllerTypeInfo.FullName}.{actionDes.MethodInfo.Name}";
|
||||||
await _eventPublisher.PublishAsync(new LogEventSource("Log:CreateReLog", options, new SysLogEntity
|
var ignoreLog = actionDes.EndpointMetadata.Any(m => m.GetType() == typeof(IgnoreLogAttribute));
|
||||||
{
|
|
||||||
Id = SnowflakeIdHelper.NextId(),
|
Stopwatch sw = new Stopwatch();
|
||||||
UserId = userId,
|
if (!ignoreLog) Log.Information("Action Starting: {0}({1})", actionName, context.ActionArguments.ToJsonString());
|
||||||
UserName = userName,
|
sw.Start();
|
||||||
Category = 5,
|
var actionContext = await next();
|
||||||
IPAddress = NetHelper.Ip,
|
sw.Stop();
|
||||||
RequestURL = httpRequest.Path,
|
// 判断是否请求成功(没有异常就是请求成功)
|
||||||
RequestDuration = (int)sw.ElapsedMilliseconds,
|
var isRequestSucceed = actionContext.Exception == null;
|
||||||
RequestMethod = httpRequest.Method,
|
//var headers = httpRequest.Headers;
|
||||||
PlatForm = string.Format("{0}-{1}", userAgent.OS.ToString(), userAgent.RawValue),
|
if (!ignoreLog && isRequestSucceed)
|
||||||
CreatorTime = DateTime.Now
|
{
|
||||||
}));
|
Log.Information("Action Finished: {0}() - Elapsed: {1:F2}ms", actionName, sw.ElapsedMilliseconds);
|
||||||
|
ConnectionConfigOptions options = userContext?.FindFirstValue(ClaimConst.CONNECTIONCONFIG)?.ToObject<ConnectionConfigOptions>();
|
||||||
var module = actionDes.EndpointMetadata.Where(x => x.GetType() == typeof(OperateLogAttribute)).FirstOrDefault() as OperateLogAttribute;
|
var userId = userContext?.FindFirstValue(ClaimConst.CLAINMUSERID);
|
||||||
if (module != null)
|
var userName = userContext?.FindFirstValue(ClaimConst.CLAINMREALNAME);
|
||||||
{
|
if (!App.HttpContext.Request.Headers.ContainsKey("Authorization"))
|
||||||
// 操作参数
|
{
|
||||||
var args = context.ActionArguments.ToJsonString();
|
var token = App.HttpContext.Request.QueryString.Value.Matches(@"[?&]token=Bearer%20([\w\.-]+)($|&)").LastOrDefault();
|
||||||
var result = (actionContext.Result as JsonResult)?.Value;
|
if (!string.IsNullOrEmpty(token))
|
||||||
|
{
|
||||||
await _eventPublisher.PublishAsync(new LogEventSource("Log:CreateOpLog", options, new SysLogEntity
|
IEnumerable<Claim> claims = JWTEncryption.ReadJwtToken(token.Replace("Bearer ", string.Empty).Replace("bearer ", string.Empty))?.Claims;
|
||||||
{
|
options = claims.FirstOrDefault(e => e.Type == ClaimConst.CONNECTIONCONFIG).ToObject<ConnectionConfigOptions>();
|
||||||
Id = SnowflakeIdHelper.NextId(),
|
userId = claims.FirstOrDefault(e => e.Type == ClaimConst.CLAINMUSERID)?.Value;
|
||||||
UserId = userId,
|
userName = claims.FirstOrDefault(e => e.Type == ClaimConst.CLAINMREALNAME)?.Value;
|
||||||
UserName = userName,
|
}
|
||||||
Category = 3,
|
}
|
||||||
IPAddress = NetHelper.Ip,
|
|
||||||
RequestURL = httpRequest.Path,
|
await _eventPublisher.PublishAsync(new LogEventSource("Log:CreateReLog", options, new SysLogEntity
|
||||||
RequestDuration = (int)sw.ElapsedMilliseconds,
|
{
|
||||||
RequestMethod = module.Action,
|
Id = SnowflakeIdHelper.NextId(),
|
||||||
PlatForm = string.Format("{0}-{1}", userAgent.OS.ToString(), userAgent.RawValue),
|
UserId = userId,
|
||||||
CreatorTime = DateTime.Now,
|
UserName = userName,
|
||||||
ModuleName = module.ModuleName,
|
Category = 5,
|
||||||
Json = string.Format("{0}应用【{1}】【{2}】", module.Action, args, result?.ToJsonString())
|
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())
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Net.Sockets;
|
using System.Net.WebSockets;
|
||||||
using System.Net.WebSockets;
|
|
||||||
using Aop.Api.Domain;
|
|
||||||
using JNPF.Common.Configuration;
|
using JNPF.Common.Configuration;
|
||||||
using JNPF.Common.Const;
|
using JNPF.Common.Const;
|
||||||
using JNPF.Common.Enums;
|
using JNPF.Common.Enums;
|
||||||
@@ -76,6 +74,7 @@ public class IMHandler : WebSocketHandler
|
|||||||
client.LoginIpAddress = client.LoginIpAddress;
|
client.LoginIpAddress = client.LoginIpAddress;
|
||||||
client.Token = message.token;
|
client.Token = message.token;
|
||||||
client.IsMobileDevice = message.mobileDevice;
|
client.IsMobileDevice = message.mobileDevice;
|
||||||
|
client.onlineTicket = claims.FirstOrDefault(e => e.Type == ClaimConst.OnlineTicket)?.Value;
|
||||||
if (client.WebSocket.State != WebSocketState.Open) return;
|
if (client.WebSocket.State != WebSocketState.Open) return;
|
||||||
await OnConnected(client.ConnectionId, client);
|
await OnConnected(client.ConnectionId, client);
|
||||||
WebSocketConnectionManager.AddToTenant(client.ConnectionId, client.ConnectionConfig?.ConfigId);
|
WebSocketConnectionManager.AddToTenant(client.ConnectionId, client.ConnectionConfig?.ConfigId);
|
||||||
@@ -177,7 +176,8 @@ public class IMHandler : WebSocketHandler
|
|||||||
tenantId = client.ConnectionConfig.ConfigId,
|
tenantId = client.ConnectionConfig.ConfigId,
|
||||||
lastLoginPlatForm = client.LoginPlatForm,
|
lastLoginPlatForm = client.LoginPlatForm,
|
||||||
isMobileDevice = client.IsMobileDevice,
|
isMobileDevice = client.IsMobileDevice,
|
||||||
token = message.token
|
token = message.token,
|
||||||
|
onlineTicket = client.onlineTicket
|
||||||
});
|
});
|
||||||
await SetOnlineUserList(client.ConnectionConfig.ConfigId, list);
|
await SetOnlineUserList(client.ConnectionConfig.ConfigId, list);
|
||||||
}
|
}
|
||||||
@@ -201,7 +201,8 @@ public class IMHandler : WebSocketHandler
|
|||||||
tenantId = client.ConnectionConfig.ConfigId,
|
tenantId = client.ConnectionConfig.ConfigId,
|
||||||
lastLoginPlatForm = client.LoginPlatForm,
|
lastLoginPlatForm = client.LoginPlatForm,
|
||||||
isMobileDevice = client.IsMobileDevice,
|
isMobileDevice = client.IsMobileDevice,
|
||||||
token = message.token
|
token = message.token,
|
||||||
|
onlineTicket = client.onlineTicket
|
||||||
});
|
});
|
||||||
await SetOnlineUserList(client.ConnectionConfig.ConfigId, list);
|
await SetOnlineUserList(client.ConnectionConfig.ConfigId, list);
|
||||||
}
|
}
|
||||||
@@ -230,7 +231,8 @@ public class IMHandler : WebSocketHandler
|
|||||||
tenantId = client.ConnectionConfig.ConfigId,
|
tenantId = client.ConnectionConfig.ConfigId,
|
||||||
lastLoginPlatForm = client.LoginPlatForm,
|
lastLoginPlatForm = client.LoginPlatForm,
|
||||||
isMobileDevice = client.IsMobileDevice,
|
isMobileDevice = client.IsMobileDevice,
|
||||||
token = message.token
|
token = message.token,
|
||||||
|
onlineTicket = client.onlineTicket
|
||||||
});
|
});
|
||||||
await SetOnlineUserList(client.ConnectionConfig.ConfigId, list);
|
await SetOnlineUserList(client.ConnectionConfig.ConfigId, list);
|
||||||
|
|
||||||
@@ -263,10 +265,11 @@ public class IMHandler : WebSocketHandler
|
|||||||
}
|
}
|
||||||
var unreadNoticeCount = await _sqlSugarClient.Queryable<MessageEntity, MessageReceiveEntity>((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 unreadNoticeCount = await _sqlSugarClient.Queryable<MessageEntity, MessageReceiveEntity>((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<MessageEntity, MessageReceiveEntity>((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 unreadMessageCount = await _sqlSugarClient.Queryable<MessageEntity, MessageReceiveEntity>((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<MessageEntity>().Where(x => x.DeleteMark == null && x.EnabledMark == 1).OrderBy(x => x.CreatorTime, OrderByType.Desc).FirstAsync();
|
var unreadSystemMessageCount = await _sqlSugarClient.Queryable<MessageEntity, MessageReceiveEntity>((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<MessageEntity, MessageReceiveEntity>((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 messageDefaultText = messageDefault == null ? string.Empty : messageDefault.Title;
|
||||||
var messageDefaultTime = messageDefault == null ? DateTime.Now : messageDefault.CreatorTime;
|
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);
|
await SendMessageToTenantAsync(client.ConnectionConfig.ConfigId, new { method = MessageSendType.online.ToString(), userId = client.UserId }.ToJsonString(), client.ConnectionId);
|
||||||
}
|
}
|
||||||
|
|||||||
199
common/Tnb.Common.Core/Job/DbJobPersistence.cs
Normal file
199
common/Tnb.Common.Core/Job/DbJobPersistence.cs
Normal file
@@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 作业持久化(数据库).
|
||||||
|
/// </summary>
|
||||||
|
public class DbJobPersistence : IJobPersistence
|
||||||
|
{
|
||||||
|
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||||
|
|
||||||
|
public DbJobPersistence(IServiceScopeFactory serviceScopeFactory)
|
||||||
|
{
|
||||||
|
_serviceScopeFactory = serviceScopeFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 作业调度服务启动时.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IEnumerable<SchedulerBuilder> Preload()
|
||||||
|
{
|
||||||
|
using var scope = _serviceScopeFactory.CreateScope();
|
||||||
|
var sqlSugarClient = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
|
||||||
|
|
||||||
|
// 获取到对应库连接
|
||||||
|
var sqlSugarScope = sqlSugarClient.AsTenant().GetConnectionScopeWithAttr<JobDetails>();
|
||||||
|
var dynamicJobCompiler = scope.ServiceProvider.GetRequiredService<DynamicJobCompiler>();
|
||||||
|
|
||||||
|
// 获取所有定义的作业
|
||||||
|
var allJobs = App.EffectiveTypes.ScanToBuilders().ToList();
|
||||||
|
|
||||||
|
//// 若数据库不存在任何作业,则直接返回
|
||||||
|
if (!sqlSugarScope.Queryable<JobDetails>().Any(u => true)) return allJobs;
|
||||||
|
|
||||||
|
// 遍历所有定义的作业
|
||||||
|
foreach (var schedulerBuilder in allJobs)
|
||||||
|
{
|
||||||
|
// 获取作业信息构建器
|
||||||
|
var jobBuilder = schedulerBuilder.GetJobBuilder();
|
||||||
|
|
||||||
|
// 加载数据库数据
|
||||||
|
var dbDetail = sqlSugarScope.Queryable<JobDetails>().First(u => u.JobId == jobBuilder.JobId);
|
||||||
|
if (dbDetail == null) continue;
|
||||||
|
|
||||||
|
// 同步数据库数据
|
||||||
|
jobBuilder.LoadFrom(dbDetail);
|
||||||
|
|
||||||
|
// 获取作业的所有数据库的触发器
|
||||||
|
var dbTriggers = sqlSugarScope.Queryable<JobTriggers>().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<JobDetails>().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<JobTriggers>().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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 作业计划初始化通知.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public SchedulerBuilder OnLoading(SchedulerBuilder builder)
|
||||||
|
{
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 作业计划Scheduler的JobDetail变化时.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context"></param>
|
||||||
|
public void OnChanged(PersistenceContext context)
|
||||||
|
{
|
||||||
|
using var scope = _serviceScopeFactory.CreateScope();
|
||||||
|
var sqlSugarClient = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
|
||||||
|
|
||||||
|
// 获取到对应库连接
|
||||||
|
var sqlSugarScope = sqlSugarClient.AsTenant().GetConnectionScopeWithAttr<JobDetails>();
|
||||||
|
|
||||||
|
var jobDetail = context.JobDetail.Adapt<JobDetails>();
|
||||||
|
|
||||||
|
// 忽略记载作业组
|
||||||
|
var ignoreRecordingTasks = new List<string>() { "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<JobDetails>().Where(u => u.JobId == jobDetail.JobId).ExecuteCommand();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 作业计划Scheduler的触发器Trigger变化时.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context"></param>
|
||||||
|
public void OnTriggerChanged(PersistenceTriggerContext context)
|
||||||
|
{
|
||||||
|
using var scope = _serviceScopeFactory.CreateScope();
|
||||||
|
var sqlSugarClient = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
|
||||||
|
|
||||||
|
// 获取到对应库连接
|
||||||
|
var sqlSugarScope = sqlSugarClient.AsTenant().GetConnectionScopeWithAttr<JobDetails>();
|
||||||
|
|
||||||
|
var jobTrigger = context.Trigger.Adapt<JobTriggers>();
|
||||||
|
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<JobTriggers>().Where(u => u.TriggerId == jobTrigger.TriggerId && u.JobId == jobTrigger.JobId).ExecuteCommand();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
common/Tnb.Common.Core/Job/DynamicJobCompiler.cs
Normal file
31
common/Tnb.Common.Core/Job/DynamicJobCompiler.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using JNPF.DependencyInjection;
|
||||||
|
using JNPF.Schedule;
|
||||||
|
|
||||||
|
namespace JNPF.Common.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 动态作业编译.
|
||||||
|
/// </summary>
|
||||||
|
public class DynamicJobCompiler : ISingleton
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 编译代码并返回其中实现 IJob 的类型.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="script">动态编译的作业代码</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ using JNPF.Common.Models;
|
|||||||
using JNPF.Common.Models.VisualDev;
|
using JNPF.Common.Models.VisualDev;
|
||||||
using JNPF.Common.Security;
|
using JNPF.Common.Security;
|
||||||
using JNPF.DependencyInjection;
|
using JNPF.DependencyInjection;
|
||||||
|
using JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
|
||||||
using JNPF.FriendlyException;
|
using JNPF.FriendlyException;
|
||||||
using JNPF.Logging;
|
using JNPF.Logging;
|
||||||
using JNPF.Systems.Entitys.Dto.Database;
|
using JNPF.Systems.Entitys.Dto.Database;
|
||||||
@@ -29,7 +30,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初始化客户端.
|
/// 初始化客户端.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static SqlSugarScope _sqlSugarClient;
|
private static SqlSugarScope? _sqlSugarClient;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用户管理器.
|
/// 用户管理器.
|
||||||
@@ -41,17 +42,24 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ConnectionStringsOptions _connectionStrings;
|
private readonly ConnectionStringsOptions _connectionStrings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 多租户配置选项.
|
||||||
|
/// </summary>
|
||||||
|
private readonly TenantOptions _tenant;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造函数.
|
/// 构造函数.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DataBaseManager(
|
public DataBaseManager(
|
||||||
IOptions<ConnectionStringsOptions> connectionOptions,
|
IOptions<ConnectionStringsOptions> connectionOptions,
|
||||||
IUserManager userManager,
|
IUserManager userManager,
|
||||||
|
IOptions<TenantOptions> tenantOptions,
|
||||||
ISqlSugarClient context)
|
ISqlSugarClient context)
|
||||||
{
|
{
|
||||||
_sqlSugarClient = (SqlSugarScope)context;
|
_sqlSugarClient = (SqlSugarScope)context;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_connectionStrings = connectionOptions.Value;
|
_connectionStrings = connectionOptions.Value;
|
||||||
|
_tenant = tenantOptions.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -61,46 +69,66 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
/// <returns>切库后的SqlSugarClient.</returns>
|
/// <returns>切库后的SqlSugarClient.</returns>
|
||||||
public SqlSugarScope ChangeDataBase(DbLinkEntity link)
|
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<ITenantFilter>(it => it.TenantId == link.Id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_sqlSugarClient.AddConnection(new ConnectionConfig()
|
if (_sqlSugarClient.AsTenant().IsAnyConnection(link.Id))
|
||||||
{
|
{
|
||||||
ConfigId = link.Id,
|
_sqlSugarClient.ChangeDatabase(link.Id);
|
||||||
DbType = ToDbType(link.DbType),
|
}
|
||||||
ConnectionString = ToConnectionString(link),
|
else
|
||||||
InitKeyType = InitKeyType.Attribute,
|
|
||||||
IsAutoCloseConnection = true
|
|
||||||
});
|
|
||||||
var db = _sqlSugarClient.GetConnectionScope(link.Id);
|
|
||||||
|
|
||||||
// 设置超时时间
|
|
||||||
db.Ado.CommandTimeOut = 30;
|
|
||||||
db.Aop.OnLogExecuted = (sql, pars) =>
|
|
||||||
{
|
{
|
||||||
var oldColor = Console.ForegroundColor;
|
_sqlSugarClient.AddConnection(new ConnectionConfig()
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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<string, SugarParameter[]>(sql, pars);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
Console.WriteLine();
|
_sqlSugarClient.ChangeDatabase(link.Id);
|
||||||
};
|
}
|
||||||
db.Aop.OnError = (ex) =>
|
|
||||||
{
|
|
||||||
Log.Error(UtilMethods.GetSqlString(db.CurrentConnectionConfig.DbType, ex.Sql, (SugarParameter[])ex.Parametres));
|
|
||||||
};
|
|
||||||
|
|
||||||
_sqlSugarClient.ChangeDatabase(link.Id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _sqlSugarClient;
|
return _sqlSugarClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,6 +169,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
else
|
else
|
||||||
flag = await _sqlSugarClient.Ado.ExecuteCommandAsync(strSql);
|
flag = await _sqlSugarClient.Ado.ExecuteCommandAsync(strSql);
|
||||||
|
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +184,9 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
||||||
_sqlSugarClient = ChangeDataBase(link);
|
_sqlSugarClient = ChangeDataBase(link);
|
||||||
|
|
||||||
return _sqlSugarClient.Ado.SqlQuery<dynamic>(strSql).Count > 0;
|
var data = _sqlSugarClient.Ado.SqlQuery<dynamic>(strSql).Count > 0;
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -180,6 +211,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
{
|
{
|
||||||
foreach (var item in dicList) flag = await _sqlSugarClient.Updateable(item).AS(table).WhereColumns(primaryField).ExecuteCommandAsync();
|
foreach (var item in dicList) flag = await _sqlSugarClient.Updateable(item).AS(table).WhereColumns(primaryField).ExecuteCommandAsync();
|
||||||
}
|
}
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,6 +232,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
if (string.IsNullOrEmpty(primaryField))
|
if (string.IsNullOrEmpty(primaryField))
|
||||||
flag = await _sqlSugarClient.Insertable(dicList).AS(table).ExecuteReturnIdentityAsync();
|
flag = await _sqlSugarClient.Insertable(dicList).AS(table).ExecuteReturnIdentityAsync();
|
||||||
|
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,6 +248,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
||||||
_sqlSugarClient = ChangeDataBase(link);
|
_sqlSugarClient = ChangeDataBase(link);
|
||||||
CreateTable(tableModel, tableFieldList);
|
CreateTable(tableModel, tableFieldList);
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,6 +273,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
}
|
}
|
||||||
//if (_sqlSugarClient.CurrentConnectionConfig.DbType == SqlSugar.DbType.MySql)
|
//if (_sqlSugarClient.CurrentConnectionConfig.DbType == SqlSugar.DbType.MySql)
|
||||||
// AddColumnMySql(tableName, tableFieldList);
|
// AddColumnMySql(tableName, tableFieldList);
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -260,6 +295,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_sqlSugarClient.DbMaintenance.DropTable(table);
|
_sqlSugarClient.DbMaintenance.DropTable(table);
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@@ -284,6 +320,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
CreateTable(tableModel, tableFieldList);
|
CreateTable(tableModel, tableFieldList);
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -309,15 +346,18 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
var sidx = pageInput.sidx.IsNotEmptyOrNull() && pageInput.sort.IsNotEmptyOrNull(); // 按前端参数排序
|
var sidx = pageInput.sidx.IsNotEmptyOrNull() && pageInput.sort.IsNotEmptyOrNull(); // 按前端参数排序
|
||||||
var defaultSidx = columnDesign.defaultSidx.IsNotEmptyOrNull() && columnDesign.sort.IsNotEmptyOrNull(); // 按模板默认排序
|
var defaultSidx = columnDesign.defaultSidx.IsNotEmptyOrNull() && columnDesign.sort.IsNotEmptyOrNull(); // 按模板默认排序
|
||||||
|
|
||||||
|
var dataRuleJson = new List<IConditionalModel>();
|
||||||
|
if (pageInput.dataRuleJson.IsNotEmptyOrNull()) dataRuleJson = _sqlSugarClient.Utilities.JsonToConditionalModels(pageInput.dataRuleJson);
|
||||||
|
|
||||||
var querJson = new List<IConditionalModel>();
|
var querJson = new List<IConditionalModel>();
|
||||||
if (pageInput.queryJson.IsNotEmptyOrNull()) querJson = _sqlSugarClient.Utilities.JsonToConditionalModels(pageInput.queryJson);
|
if (pageInput.queryJson.IsNotEmptyOrNull()) querJson = _sqlSugarClient.Utilities.JsonToConditionalModels(pageInput.queryJson);
|
||||||
|
|
||||||
var superQueryJson = new List<IConditionalModel>();
|
var superQueryJson = new List<IConditionalModel>();
|
||||||
if (pageInput.superQueryJson.IsNotEmptyOrNull()) superQueryJson = _sqlSugarClient.Utilities.JsonToConditionalModels(pageInput.superQueryJson);
|
if (pageInput.superQueryJson.IsNotEmptyOrNull()) superQueryJson = _sqlSugarClient.Utilities.JsonToConditionalModels(pageInput.superQueryJson);
|
||||||
// var sql = _sqlSugarClient.SqlQueryable<object>(strSql)
|
// var sql = _sqlSugarClient.SqlQueryable<object>(strSql)
|
||||||
// .Where(querJson).Where(superQueryJson).Where(dataPermissions).ToSqlString();
|
// .Where(dataRuleJson).Where(querJson).Where(superQueryJson).Where(dataPermissions).ToSqlString();
|
||||||
DataTable dt = _sqlSugarClient.SqlQueryable<object>(strSql)
|
DataTable dt = _sqlSugarClient.SqlQueryable<object>(strSql)
|
||||||
.Where(querJson).Where(superQueryJson).Where(dataPermissions)
|
.Where(dataRuleJson).Where(querJson).Where(superQueryJson).Where(dataPermissions)
|
||||||
.OrderByIF(sidx, pageInput.sidx + " " + pageInput.sort).OrderByIF(!sidx && defaultSidx, columnDesign.defaultSidx + " " + columnDesign.sort)
|
.OrderByIF(sidx, pageInput.sidx + " " + pageInput.sort).OrderByIF(!sidx && defaultSidx, columnDesign.defaultSidx + " " + columnDesign.sort)
|
||||||
.ToDataTablePage(pageInput.currentPage, pageInput.pageSize, ref total);
|
.ToDataTablePage(pageInput.currentPage, pageInput.pageSize, ref total);
|
||||||
|
|
||||||
@@ -329,7 +369,7 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
dt.Columns[i].ColumnName = outColumnName.TryGetValue(dt.Columns[i].ColumnName.ToUpper(), out resultKey) == true ? outColumnName[dt.Columns[i].ColumnName.ToUpper()] : dt.Columns[i].ColumnName.ToUpper();
|
dt.Columns[i].ColumnName = outColumnName.TryGetValue(dt.Columns[i].ColumnName.ToUpper(), out resultKey) == true ? outColumnName[dt.Columns[i].ColumnName.ToUpper()] : dt.Columns[i].ColumnName.ToUpper();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new PageResult<Dictionary<string, object>>()
|
var data = new PageResult<Dictionary<string, object>>()
|
||||||
{
|
{
|
||||||
pagination = new PageResult()
|
pagination = new PageResult()
|
||||||
{
|
{
|
||||||
@@ -339,6 +379,10 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
},
|
},
|
||||||
list = dt.ToObject<List<Dictionary<string, string>>>().ToObject<List<Dictionary<string, object>>>()
|
list = dt.ToObject<List<Dictionary<string, string>>>().ToObject<List<Dictionary<string, object>>>()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
|
|
||||||
|
return data;
|
||||||
//}
|
//}
|
||||||
//catch (Exception ex)
|
//catch (Exception ex)
|
||||||
//{
|
//{
|
||||||
@@ -357,7 +401,26 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
||||||
_sqlSugarClient = ChangeDataBase(link);
|
_sqlSugarClient = ChangeDataBase(link);
|
||||||
|
|
||||||
return _sqlSugarClient.DbMaintenance.IsAnyTable(table, false);
|
var data = _sqlSugarClient.DbMaintenance.IsAnyTable(table, false);
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表是否存在数据.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="link">数据连接.</param>
|
||||||
|
/// <param name="table">表名.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool IsAnyData(DbLinkEntity link, string table)
|
||||||
|
{
|
||||||
|
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
||||||
|
_sqlSugarClient = ChangeDataBase(link);
|
||||||
|
|
||||||
|
var data = _sqlSugarClient.Queryable<dynamic>().AS(table).Any();
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -372,7 +435,10 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
||||||
_sqlSugarClient = ChangeDataBase(link);
|
_sqlSugarClient = ChangeDataBase(link);
|
||||||
|
|
||||||
return _sqlSugarClient.DbMaintenance.IsAnyColumn(table, column, false);
|
var data = _sqlSugarClient.DbMaintenance.IsAnyColumn(table, column, false);
|
||||||
|
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -385,41 +451,20 @@ public class DataBaseManager : IDataBaseManager, ITransient
|
|||||||
{
|
{
|
||||||
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id) _sqlSugarClient = ChangeDataBase(link);
|
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id) _sqlSugarClient = ChangeDataBase(link);
|
||||||
|
|
||||||
List<DbTableFieldModel> list;
|
var list = _sqlSugarClient.DbMaintenance.GetColumnInfosByTableName(tableName, false);
|
||||||
if (link.DbType == SqlSugar.DbType.PostgreSQL.ToString())
|
|
||||||
{
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
var sql = @"SELECT pcolumn.table_name AS tableName,pcolumn.column_name AS field,pcolumn.udt_name AS dataType,
|
return list.Adapt<List<DbTableFieldModel>>();
|
||||||
pcolumn.column_default as defaults,col_description(pclass.oid, pcolumn.ordinal_position) AS fieldName,
|
|
||||||
CASE WHEN pcolumn.numeric_scale>0 THEN pcolumn.numeric_precision ELSE COALESCE(pcolumn.character_maximum_length,0) END AS dataLength,
|
|
||||||
CASE WHEN pcolumn.is_nullable = 'YES' THEN 1 ELSE 0 END AS allowNull,
|
|
||||||
CASE WHEN pcolumn.column_default LIKE 'nextval%' THEN true ELSE false END AS identity,
|
|
||||||
CASE WHEN pkey.colname = pcolumn.column_name THEN true ELSE false END AS primaryKey
|
|
||||||
FROM information_schema.columns pcolumn
|
|
||||||
INNER JOIN pg_class pclass ON pcolumn.table_name = pclass.relname
|
|
||||||
LEFT JOIN (
|
|
||||||
SELECT pg_class.relname,pg_attribute.attname AS colname FROM
|
|
||||||
pg_constraint INNER JOIN pg_class
|
|
||||||
ON pg_constraint.conrelid = pg_class.oid
|
|
||||||
INNER JOIN pg_attribute ON pg_attribute.attrelid = pg_class.oid
|
|
||||||
and pg_attribute.attnum = pg_constraint.conkey[1]
|
|
||||||
INNER JOIN pg_type ON pg_type.oid = pg_attribute.atttypid
|
|
||||||
where pg_constraint.contype='p'
|
|
||||||
) pkey ON pcolumn.table_name = pkey.relname
|
|
||||||
WHERE pcolumn.table_name='{0}' ORDER BY ordinal_position";
|
|
||||||
list = _sqlSugarClient.SqlQueryable<DbTableFieldModel>(string.Format(sql, tableName)).ToList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
list = _sqlSugarClient.DbMaintenance.GetColumnInfosByTableName(tableName, false).Adapt<List<DbTableFieldModel>>();
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> GetPrimaries(DbLinkEntity? link, string tableName)
|
public List<string> GetPrimaries(DbLinkEntity? link, string tableName)
|
||||||
{
|
{
|
||||||
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id) _sqlSugarClient = ChangeDataBase(link);
|
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
||||||
|
_sqlSugarClient = ChangeDataBase(link);
|
||||||
|
|
||||||
return _sqlSugarClient.DbMaintenance.GetPrimaries(tableName);
|
var data = _sqlSugarClient.DbMaintenance.GetPrimaries(tableName);
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -432,7 +477,9 @@ WHERE pcolumn.table_name='{0}' ORDER BY ordinal_position";
|
|||||||
{
|
{
|
||||||
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
||||||
_sqlSugarClient = ChangeDataBase(link);
|
_sqlSugarClient = ChangeDataBase(link);
|
||||||
return _sqlSugarClient.Queryable<dynamic>().AS(tableName).ToDataTable();
|
var data = _sqlSugarClient.Queryable<dynamic>().AS(tableName).ToDataTable();
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -452,7 +499,37 @@ WHERE pcolumn.table_name='{0}' ORDER BY ordinal_position";
|
|||||||
if (_sqlSugarClient.CurrentConnectionConfig.DbType == SqlSugar.DbType.Oracle)
|
if (_sqlSugarClient.CurrentConnectionConfig.DbType == SqlSugar.DbType.Oracle)
|
||||||
strSql = strSql.Replace(";", string.Empty);
|
strSql = strSql.Replace(";", string.Empty);
|
||||||
|
|
||||||
return _sqlSugarClient.Ado.GetDataTable(strSql, parameters);
|
var data = _sqlSugarClient.Ado.GetDataTable(strSql, parameters);
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
|
||||||
|
throw Oops.Oh(ErrorCode.D1511);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据链接获取数据.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="link">数据连接.</param>
|
||||||
|
/// <param name="strSql">sql语句.</param>
|
||||||
|
/// <param name="parameters">参数.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public DataTable GetInterFaceDataCopyNew(DbLinkEntity link, string strSql, params SugarParameter[] parameters)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
||||||
|
_sqlSugarClient = ChangeDataBase(link);
|
||||||
|
|
||||||
|
if (_sqlSugarClient.CurrentConnectionConfig.DbType == SqlSugar.DbType.Oracle)
|
||||||
|
strSql = strSql.Replace(";", string.Empty);
|
||||||
|
|
||||||
|
var data = _sqlSugarClient.CopyNew().Ado.GetDataTable(strSql, parameters);
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@@ -475,7 +552,9 @@ WHERE pcolumn.table_name='{0}' ORDER BY ordinal_position";
|
|||||||
if (_sqlSugarClient.CurrentConnectionConfig.DbType == SqlSugar.DbType.Oracle)
|
if (_sqlSugarClient.CurrentConnectionConfig.DbType == SqlSugar.DbType.Oracle)
|
||||||
strSql = strSql.Replace(";", string.Empty);
|
strSql = strSql.Replace(";", string.Empty);
|
||||||
|
|
||||||
_sqlSugarClient.Ado.ExecuteCommand(strSql, parameters);
|
_sqlSugarClient.CopyNew().Ado.ExecuteCommand(strSql, parameters);
|
||||||
|
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -498,6 +577,8 @@ WHERE pcolumn.table_name='{0}' ORDER BY ordinal_position";
|
|||||||
|
|
||||||
data.tableFieldList = ViewDataTypeConversion(data.tableFieldList, _sqlSugarClient.CurrentConnectionConfig.DbType);
|
data.tableFieldList = ViewDataTypeConversion(data.tableFieldList, _sqlSugarClient.CurrentConnectionConfig.DbType);
|
||||||
|
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,6 +597,7 @@ WHERE pcolumn.table_name='{0}' ORDER BY ordinal_position";
|
|||||||
//var modelList = _sqlSugarClient.Ado.SqlQuery<DynamicDbTableModel>(sql).ToList();
|
//var modelList = _sqlSugarClient.Ado.SqlQuery<DynamicDbTableModel>(sql).ToList();
|
||||||
var modelList = _sqlSugarClient.Ado.SqlQuery<DatabaseTableListOutput>(sql).ToList();
|
var modelList = _sqlSugarClient.Ado.SqlQuery<DatabaseTableListOutput>(sql).ToList();
|
||||||
//return modelList.Select(x => new DatabaseTableListOutput { table = x.F_TABLE, tableName = x.F_TABLENAME, sum = x.F_SUM.ParseToInt() }).ToList();
|
//return modelList.Select(x => new DatabaseTableListOutput { table = x.F_TABLE, tableName = x.F_TABLENAME, sum = x.F_SUM.ParseToInt() }).ToList();
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
return modelList;
|
return modelList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,7 +611,9 @@ WHERE pcolumn.table_name='{0}' ORDER BY ordinal_position";
|
|||||||
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
||||||
_sqlSugarClient = ChangeDataBase(link);
|
_sqlSugarClient = ChangeDataBase(link);
|
||||||
|
|
||||||
return _sqlSugarClient.DbMaintenance.GetTableInfoList(false);
|
var data = _sqlSugarClient.DbMaintenance.GetTableInfoList(false);
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -547,8 +631,7 @@ WHERE pcolumn.table_name='{0}' ORDER BY ordinal_position";
|
|||||||
|
|
||||||
RefAsync<int> totalNumber = 0;
|
RefAsync<int> totalNumber = 0;
|
||||||
var list = await _sqlSugarClient.SqlQueryable<object>(dbSql).ToDataTablePageAsync(pageIndex, pageSize, totalNumber);
|
var list = await _sqlSugarClient.SqlQueryable<object>(dbSql).ToDataTablePageAsync(pageIndex, pageSize, totalNumber);
|
||||||
|
var data = PageResult<dynamic>.SqlSugarPageResult(new SqlSugarPagedList<dynamic>()
|
||||||
return PageResult<dynamic>.SqlSugarPageResult(new SqlSugarPagedList<dynamic>()
|
|
||||||
{
|
{
|
||||||
list = ToDynamicList(list),
|
list = ToDynamicList(list),
|
||||||
pagination = new Pagination()
|
pagination = new Pagination()
|
||||||
@@ -558,6 +641,8 @@ WHERE pcolumn.table_name='{0}' ORDER BY ordinal_position";
|
|||||||
Total = totalNumber
|
Total = totalNumber
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -573,7 +658,9 @@ WHERE pcolumn.table_name='{0}' ORDER BY ordinal_position";
|
|||||||
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
if (link != null && _sqlSugarClient.CurrentConnectionConfig.ConfigId != link.Id)
|
||||||
_sqlSugarClient = ChangeDataBase(link);
|
_sqlSugarClient = ChangeDataBase(link);
|
||||||
|
|
||||||
return await _sqlSugarClient.Queryable<TEntity>().ToPageListAsync(pageIndex, pageSize);
|
var data = await _sqlSugarClient.Queryable<TEntity>().ToPageListAsync(pageIndex, pageSize);
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -590,6 +677,7 @@ WHERE pcolumn.table_name='{0}' ORDER BY ordinal_position";
|
|||||||
|
|
||||||
List<Dictionary<string, object>> dc = _sqlSugarClient.Utilities.DataTableToDictionaryList(dt); // 5.0.23版本支持
|
List<Dictionary<string, object>> dc = _sqlSugarClient.Utilities.DataTableToDictionaryList(dt); // 5.0.23版本支持
|
||||||
var isOk = await _sqlSugarClient.Insertable(dc).AS(table).ExecuteCommandAsync();
|
var isOk = await _sqlSugarClient.Insertable(dc).AS(table).ExecuteCommandAsync();
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
return isOk > 0;
|
return isOk > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,6 +714,7 @@ WHERE pcolumn.table_name='{0}' ORDER BY ordinal_position";
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -658,9 +747,15 @@ WHERE pcolumn.table_name='{0}' ORDER BY ordinal_position";
|
|||||||
_sqlSugarClient = ChangeDataBase(link);
|
_sqlSugarClient = ChangeDataBase(link);
|
||||||
|
|
||||||
if (_sqlSugarClient.Ado.IsValidConnection())
|
if (_sqlSugarClient.Ado.IsValidConnection())
|
||||||
|
{
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
_sqlSugarClient.ChangeDatabase(_connectionStrings.ConfigId);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -15,255 +15,272 @@ namespace JNPF.Common.Core.Manager;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IDataBaseManager
|
public interface IDataBaseManager
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取多租户Link.
|
/// 获取多租户Link.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tenantId">租户ID.</param>
|
/// <param name="tenantId">租户ID.</param>
|
||||||
/// <param name="tenantName">租户数据库.</param>
|
/// <param name="tenantName">租户数据库.</param>
|
||||||
/// <returns>租户的DBLink实体对象.</returns>
|
/// <returns>租户的DBLink实体对象.</returns>
|
||||||
DbLinkEntity GetTenantDbLink(string tenantId, string tenantName);
|
DbLinkEntity GetTenantDbLink(string tenantId, string tenantName);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 数据库切换.
|
/// 数据库切换.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <returns>切库后的SqlSugarClient.</returns>
|
/// <returns>切库后的SqlSugarClient.</returns>
|
||||||
SqlSugarScope ChangeDataBase(DbLinkEntity link);
|
SqlSugarScope ChangeDataBase(DbLinkEntity link);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行Sql(查询).
|
/// 执行Sql(查询).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="strSql">sql语句.</param>
|
/// <param name="strSql">sql语句.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<int> ExecuteSql(DbLinkEntity link, string strSql);
|
Task<int> ExecuteSql(DbLinkEntity link, string strSql);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 条件动态过滤.
|
/// 条件动态过滤.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="strSql">sql语句.</param>
|
/// <param name="strSql">sql语句.</param>
|
||||||
/// <returns>条件是否成立.</returns>
|
/// <returns>条件是否成立.</returns>
|
||||||
bool WhereDynamicFilter(DbLinkEntity link, string strSql);
|
bool WhereDynamicFilter(DbLinkEntity link, string strSql);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行Sql(新增、修改).
|
/// 执行Sql(新增、修改).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="table">表名.</param>
|
/// <param name="table">表名.</param>
|
||||||
/// <param name="dicList">数据.</param>
|
/// <param name="dicList">数据.</param>
|
||||||
/// <param name="primaryField">主键字段.</param>
|
/// <param name="primaryField">主键字段.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<int> ExecuteSql(DbLinkEntity link, string table, List<Dictionary<string, object>> dicList, string primaryField = "");
|
Task<int> ExecuteSql(DbLinkEntity link, string table, List<Dictionary<string, object>> dicList, string primaryField = "");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行Sql 新增 并返回自增长Id.
|
/// 执行Sql 新增 并返回自增长Id.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="table">表名.</param>
|
/// <param name="table">表名.</param>
|
||||||
/// <param name="dicList">数据.</param>
|
/// <param name="dicList">数据.</param>
|
||||||
/// <param name="primaryField">主键字段.</param>
|
/// <param name="primaryField">主键字段.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<int> ExecuteReturnIdentityAsync(DbLinkEntity link, string table, List<Dictionary<string, object>> dicList, string primaryField = "");
|
Task<int> ExecuteReturnIdentityAsync(DbLinkEntity link, string table, List<Dictionary<string, object>> dicList, string primaryField = "");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建表.
|
/// 创建表.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="tableModel">表对象.</param>
|
/// <param name="tableModel">表对象.</param>
|
||||||
/// <param name="tableFieldList">字段对象.</param>
|
/// <param name="tableFieldList">字段对象.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<bool> Create(DbLinkEntity link, DbTableModel tableModel, List<DbTableFieldModel> tableFieldList);
|
Task<bool> Create(DbLinkEntity link, DbTableModel tableModel, List<DbTableFieldModel> tableFieldList);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// sqlsugar添加表字段.
|
/// sqlsugar添加表字段.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tableName">表名.</param>
|
/// <param name="tableName">表名.</param>
|
||||||
/// <param name="tableFieldList">表字段集合.</param>
|
/// <param name="tableFieldList">表字段集合.</param>
|
||||||
void AddTableColumn(DbLinkEntity link, string tableName, List<DbTableFieldModel> tableFieldList);
|
void AddTableColumn(DbLinkEntity link ,string tableName, List<DbTableFieldModel> tableFieldList);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除表.
|
/// 删除表.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="table">表名.</param>
|
/// <param name="table">表名.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
bool Delete(DbLinkEntity link, string table);
|
bool Delete(DbLinkEntity link, string table);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 修改表.
|
/// 修改表.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="oldTable">旧表名称.</param>
|
/// <param name="oldTable">旧表名称.</param>
|
||||||
/// <param name="tableModel">表对象.</param>
|
/// <param name="tableModel">表对象.</param>
|
||||||
/// <param name="tableFieldList">字段对象.</param>
|
/// <param name="tableFieldList">字段对象.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<bool> Update(DbLinkEntity link, string oldTable, DbTableModel tableModel, List<DbTableFieldModel> tableFieldList);
|
Task<bool> Update(DbLinkEntity link, string oldTable, DbTableModel tableModel, List<DbTableFieldModel> tableFieldList);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据链接获取分页数据.
|
/// 根据链接获取分页数据.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="strSql">Sql语句.</param>
|
/// <param name="strSql">Sql语句.</param>
|
||||||
/// <param name="pageInput">页数.</param>
|
/// <param name="pageInput">页数.</param>
|
||||||
/// <param name="columnDesign">列配置.</param>
|
/// <param name="columnDesign">列配置.</param>
|
||||||
/// <param name="dataPermissions">数据权限.</param>
|
/// <param name="dataPermissions">数据权限.</param>
|
||||||
/// <param name="outColumnName">输出列名称.</param>
|
/// <param name="outColumnName">输出列名称.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
PageResult<Dictionary<string, object>> GetInterFaceData(DbLinkEntity link, string strSql, VisualDevModelListQueryInput pageInput, MainBeltViceQueryModel columnDesign, List<IConditionalModel> dataPermissions, Dictionary<string, string> outColumnName = null);
|
PageResult<Dictionary<string, object>> GetInterFaceData(DbLinkEntity link, string strSql, VisualDevModelListQueryInput pageInput, MainBeltViceQueryModel columnDesign, List<IConditionalModel> dataPermissions, Dictionary<string, string> outColumnName = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 表是否存在.
|
/// 表是否存在.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="table">表名.</param>
|
/// <param name="table">表名.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
bool IsAnyTable(DbLinkEntity link, string table);
|
bool IsAnyTable(DbLinkEntity link, string table);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 表字段是否存在.
|
/// 表是否存在数据.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="table">表名.</param>
|
/// <param name="table">表名.</param>
|
||||||
/// <param name="column">表字段名.</param>
|
/// <returns></returns>
|
||||||
/// <returns></returns>
|
bool IsAnyData(DbLinkEntity link, string table);
|
||||||
bool IsAnyColumn(DbLinkEntity link, string table, string column);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取表字段列表.
|
/// 表字段是否存在.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="tableName">表名.</param>
|
/// <param name="table">表名.</param>
|
||||||
/// <returns></returns>
|
/// <param name="column">表字段名.</param>
|
||||||
List<DbTableFieldModel> GetFieldList(DbLinkEntity? link, string? tableName);
|
/// <returns></returns>
|
||||||
|
bool IsAnyColumn(DbLinkEntity link, string table, string column);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取表的主键
|
/// 获取表字段列表.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link"></param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="tableName"></param>
|
/// <param name="tableName">表名.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
List<string> GetPrimaries(DbLinkEntity? link, string tableName);
|
List<DbTableFieldModel> GetFieldList(DbLinkEntity? link, string? tableName);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取表数据.
|
/// 获取表数据.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="tableName">表名.</param>
|
/// <param name="tableName">表名.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
DataTable GetData(DbLinkEntity link, string tableName);
|
DataTable GetData(DbLinkEntity link, string tableName);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据链接获取数据.
|
/// 根据链接获取数据.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="strSql">Sql语句.</param>
|
/// <param name="strSql">Sql语句.</param>
|
||||||
/// <param name="parameters">参数.</param>
|
/// <param name="parameters">参数.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
DataTable GetInterFaceData(DbLinkEntity link, string strSql, params SugarParameter[] parameters);
|
DataTable GetInterFaceData(DbLinkEntity link, string strSql, params SugarParameter[] parameters);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取表信息.
|
/// 根据链接获取数据.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="tableName">表名.</param>
|
/// <param name="strSql">sql语句.</param>
|
||||||
/// <returns></returns>
|
/// <param name="parameters">参数.</param>
|
||||||
DatabaseTableInfoOutput GetDataBaseTableInfo(DbLinkEntity link, string tableName);
|
/// <returns></returns>
|
||||||
|
public DataTable GetInterFaceDataCopyNew(DbLinkEntity link, string strSql, params SugarParameter[] parameters);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取数据库表信息.
|
/// 获取表信息.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <returns></returns>
|
/// <param name="tableName">表名.</param>
|
||||||
List<DatabaseTableListOutput> GetDBTableList(DbLinkEntity link);
|
/// <returns></returns>
|
||||||
|
DatabaseTableInfoOutput GetDataBaseTableInfo(DbLinkEntity link, string tableName);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取数据库表信息.
|
/// 获取数据库表信息.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
List<DbTableInfo> GetTableInfos(DbLinkEntity link);
|
List<DatabaseTableListOutput> GetDBTableList(DbLinkEntity link);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取数据表分页(SQL语句).
|
/// 获取数据库表信息.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="dbSql">数据SQL.</param>
|
/// <returns></returns>
|
||||||
/// <param name="pageIndex">页数.</param>
|
List<DbTableInfo> GetTableInfos(DbLinkEntity link);
|
||||||
/// <param name="pageSize">条数.</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<dynamic> GetDataTablePage(DbLinkEntity link, string dbSql, int pageIndex, int pageSize);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取数据表分页(实体).
|
/// 获取数据表分页(SQL语句).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TEntity">T.</typeparam>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="dbSql">数据SQL.</param>
|
||||||
/// <param name="pageIndex">页数.</param>
|
/// <param name="pageIndex">页数.</param>
|
||||||
/// <param name="pageSize">条数.</param>
|
/// <param name="pageSize">条数.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<TEntity>> GetDataTablePage<TEntity>(DbLinkEntity link, int pageIndex, int pageSize);
|
Task<dynamic> GetDataTablePage(DbLinkEntity link, string dbSql, int pageIndex, int pageSize);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 使用存储过程.
|
/// 获取数据表分页(实体).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <typeparam name="TEntity">T.</typeparam>
|
||||||
/// <param name="stored">存储过程名称.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="parameters">参数.</param>
|
/// <param name="pageIndex">页数.</param>
|
||||||
void UseStoredProcedure(DbLinkEntity link, string stored, List<SugarParameter> parameters);
|
/// <param name="pageSize">条数.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<List<TEntity>> GetDataTablePage<TEntity>(DbLinkEntity link, int pageIndex, int pageSize);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 测试数据库连接.
|
/// 使用存储过程.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <returns></returns>
|
/// <param name="stored">存储过程名称.</param>
|
||||||
bool IsConnection(DbLinkEntity link);
|
/// <param name="parameters">参数.</param>
|
||||||
|
void UseStoredProcedure(DbLinkEntity link, string stored, List<SugarParameter> parameters);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 同步数据.
|
/// 测试数据库连接.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="dt">同步数据.</param>
|
/// <returns></returns>
|
||||||
/// <param name="table">表.</param>
|
bool IsConnection(DbLinkEntity link);
|
||||||
/// <returns></returns>
|
|
||||||
Task<bool> SyncData(DbLinkEntity link, DataTable dt, string table);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 同步表操作.
|
/// 同步数据.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="linkFrom">原数据库.</param>
|
/// <param name="link">数据连接.</param>
|
||||||
/// <param name="linkTo">目前数据库.</param>
|
/// <param name="dt">同步数据.</param>
|
||||||
/// <param name="table">表名称.</param>
|
/// <param name="table">表.</param>
|
||||||
/// <param name="type">操作类型.</param>
|
/// <returns></returns>
|
||||||
/// <param name="fieldType">数据类型.</param>
|
Task<bool> SyncData(DbLinkEntity link, DataTable dt, string table);
|
||||||
void SyncTable(DbLinkEntity linkFrom, DbLinkEntity linkTo, string table, int type, Dictionary<string, string> fieldType);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 视图数据类型转换.
|
/// 同步表操作.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fields">字段数据.</param>
|
/// <param name="linkFrom">原数据库.</param>
|
||||||
/// <param name="databaseType">数据库类型.</param>
|
/// <param name="linkTo">目前数据库.</param>
|
||||||
List<TableFieldOutput> ViewDataTypeConversion(List<TableFieldOutput> fields, SqlSugar.DbType databaseType);
|
/// <param name="table">表名称.</param>
|
||||||
|
/// <param name="type">操作类型.</param>
|
||||||
|
/// <param name="fieldType">数据类型.</param>
|
||||||
|
void SyncTable(DbLinkEntity linkFrom, DbLinkEntity linkTo, string table, int type, Dictionary<string, string> fieldType);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 转换数据库类型.
|
/// 视图数据类型转换.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dbType">数据库类型.</param>
|
/// <param name="fields">字段数据.</param>
|
||||||
/// <returns></returns>
|
/// <param name="databaseType">数据库类型.</param>
|
||||||
SqlSugar.DbType ToDbType(string dbType);
|
List<TableFieldOutput> ViewDataTypeConversion(List<TableFieldOutput> fields, SqlSugar.DbType databaseType);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 转换连接字符串.
|
/// 转换数据库类型.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dbLinkEntity">数据连接.</param>
|
/// <param name="dbType">数据库类型.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
string ToConnectionString(DbLinkEntity dbLinkEntity);
|
SqlSugar.DbType ToDbType(string dbType);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行增删改sql.
|
/// 转换连接字符串.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">数据连接.</param>
|
/// <param name="dbLinkEntity">数据连接.</param>
|
||||||
/// <param name="strSql">sql语句.</param>
|
/// <returns></returns>
|
||||||
/// <param name="parameters">参数.</param>
|
string ToConnectionString(DbLinkEntity dbLinkEntity);
|
||||||
void ExecuteCommand(DbLinkEntity link, string strSql, params SugarParameter[] parameters);
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行增删改sql.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="link">数据连接.</param>
|
||||||
|
/// <param name="strSql">sql语句.</param>
|
||||||
|
/// <param name="parameters">参数.</param>
|
||||||
|
void ExecuteCommand(DbLinkEntity link, string strSql, params SugarParameter[] parameters);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取表的主键
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="link"></param>
|
||||||
|
/// <param name="tableName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<string> GetPrimaries(DbLinkEntity? link, string tableName);
|
||||||
}
|
}
|
||||||
@@ -91,6 +91,7 @@ namespace JNPF.Common.Core.Manager.Files
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
filePath = filePath.Replace(@",", "/");
|
||||||
switch (KeyVariable.FileStoreType)
|
switch (KeyVariable.FileStoreType)
|
||||||
{
|
{
|
||||||
case OSSProviderType.Invalid:
|
case OSSProviderType.Invalid:
|
||||||
@@ -169,6 +170,7 @@ namespace JNPF.Common.Core.Manager.Files
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
filePath = filePath.Replace(@",", "/");
|
||||||
switch (KeyVariable.FileStoreType)
|
switch (KeyVariable.FileStoreType)
|
||||||
{
|
{
|
||||||
case OSSProviderType.Invalid:
|
case OSSProviderType.Invalid:
|
||||||
@@ -196,6 +198,7 @@ namespace JNPF.Common.Core.Manager.Files
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
filePath = filePath.Replace(@",", "/");
|
||||||
switch (KeyVariable.FileStoreType)
|
switch (KeyVariable.FileStoreType)
|
||||||
{
|
{
|
||||||
case OSSProviderType.Invalid:
|
case OSSProviderType.Invalid:
|
||||||
@@ -221,6 +224,7 @@ namespace JNPF.Common.Core.Manager.Files
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
filePath = filePath.Replace(@",", "/");
|
||||||
switch (KeyVariable.FileStoreType)
|
switch (KeyVariable.FileStoreType)
|
||||||
{
|
{
|
||||||
case OSSProviderType.Invalid:
|
case OSSProviderType.Invalid:
|
||||||
@@ -248,6 +252,7 @@ namespace JNPF.Common.Core.Manager.Files
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
filePath = filePath.Replace(@",", "/");
|
||||||
switch (KeyVariable.FileStoreType)
|
switch (KeyVariable.FileStoreType)
|
||||||
{
|
{
|
||||||
case OSSProviderType.Invalid:
|
case OSSProviderType.Invalid:
|
||||||
@@ -266,6 +271,36 @@ namespace JNPF.Common.Core.Manager.Files
|
|||||||
throw Oops.Oh(ErrorCode.D1804);
|
throw Oops.Oh(ErrorCode.D1804);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 复制文件.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath">源文件地址.</param>
|
||||||
|
/// <param name="toFilePath">剪切地址.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task CopyFile(string filePath, string toFilePath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
filePath = filePath.Replace(@",", "/");
|
||||||
|
switch (KeyVariable.FileStoreType)
|
||||||
|
{
|
||||||
|
case OSSProviderType.Invalid:
|
||||||
|
FileHelper.CopyFile(filePath, toFilePath);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
filePath = filePath.Replace(@"\", "/");
|
||||||
|
var bucketName = KeyVariable.BucketName;
|
||||||
|
await _oSSServiceFactory.Create(KeyVariable.FileStoreType.ToString()).CopyObjectAsync(bucketName, filePath, bucketName, toFilePath);
|
||||||
|
await _oSSServiceFactory.Create(KeyVariable.FileStoreType.ToString()).RemoveObjectAsync(bucketName, filePath);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (AppFriendlyException ex)
|
||||||
|
{
|
||||||
|
throw Oops.Oh(ErrorCode.D1804);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 导入导出(json文件)
|
#region 导入导出(json文件)
|
||||||
@@ -286,8 +321,7 @@ namespace JNPF.Common.Core.Manager.Files
|
|||||||
var stream = new MemoryStream(byteList);
|
var stream = new MemoryStream(byteList);
|
||||||
await UploadFileByType(stream, _filePath, _fileName);
|
await UploadFileByType(stream, _filePath, _fileName);
|
||||||
_cacheManager.Set(_fileName, string.Empty);
|
_cacheManager.Set(_fileName, string.Empty);
|
||||||
return new
|
return new {
|
||||||
{
|
|
||||||
name = _fileName,
|
name = _fileName,
|
||||||
url = string.Format("/api/file/Download?encryption={0}", DESCEncryption.Encrypt(string.Format("{0}|{1}|json", _userManager.UserId, _fileName), "JNPF"))
|
url = string.Format("/api/file/Download?encryption={0}", DESCEncryption.Encrypt(string.Format("{0}|{1}|json", _userManager.UserId, _fileName), "JNPF"))
|
||||||
};
|
};
|
||||||
@@ -375,7 +409,8 @@ namespace JNPF.Common.Core.Manager.Files
|
|||||||
fs.Flush();
|
fs.Flush();
|
||||||
fs.Close();
|
fs.Close();
|
||||||
Stream stream = new FileStream(Path.Combine(directoryPath, saveFileName), FileMode.Open, FileAccess.Read, FileShare.Read);
|
Stream stream = new FileStream(Path.Combine(directoryPath, saveFileName), FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
var flag = await UploadFileByType(stream, GetPathByType(input.type), saveFileName);
|
GetChunkModel(input, saveFileName);
|
||||||
|
var flag = await UploadFileByType(stream, input.folder, saveFileName);
|
||||||
var fileSize = stream.Length;
|
var fileSize = stream.Length;
|
||||||
if (flag)
|
if (flag)
|
||||||
{
|
{
|
||||||
@@ -383,7 +418,7 @@ namespace JNPF.Common.Core.Manager.Files
|
|||||||
stream.Close();
|
stream.Close();
|
||||||
FileHelper.DeleteDirectory(directoryPath);
|
FileHelper.DeleteDirectory(directoryPath);
|
||||||
}
|
}
|
||||||
return new FileControlsModel { name = saveFileName, url = string.Format("/api/file/Image/annex/{0}", saveFileName), fileExtension = input.extension, fileSize = input.fileSize.ParseToLong() };
|
return new FileControlsModel { name = input.fileName, url = string.Format("/api/file/Image/annex/{0}", input.fileName), fileExtension = input.extension, fileSize = input.fileSize.ParseToLong(), fileName = input.fileName };
|
||||||
}
|
}
|
||||||
catch (AppFriendlyException ex)
|
catch (AppFriendlyException ex)
|
||||||
{
|
{
|
||||||
@@ -467,5 +502,39 @@ namespace JNPF.Common.Core.Manager.Files
|
|||||||
}
|
}
|
||||||
return fileName;
|
return fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取地址和文件名.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <param name="saveFileName"></param>
|
||||||
|
public void GetChunkModel(ChunkModel input, string saveFileName)
|
||||||
|
{
|
||||||
|
var floder = GetPathByType(input.type);
|
||||||
|
var fileNameStr = string.Empty;
|
||||||
|
// 自定义路径
|
||||||
|
if (input.pathType.Equals("selfPath"))
|
||||||
|
{
|
||||||
|
if (input.isAccount.Equals("1"))
|
||||||
|
{
|
||||||
|
floder = Path.Combine(floder, _userManager.User.Account);
|
||||||
|
fileNameStr = Path.Combine(fileNameStr, _userManager.User.Account);
|
||||||
|
}
|
||||||
|
if (input.folder.IsNotEmptyOrNull())
|
||||||
|
{
|
||||||
|
floder = Path.Combine(floder, input.folder.Trim('/'));
|
||||||
|
fileNameStr = Path.Combine(fileNameStr, input.folder);
|
||||||
|
}
|
||||||
|
fileNameStr = Path.Combine(fileNameStr, saveFileName);
|
||||||
|
fileNameStr = fileNameStr.Replace("\\", ",");
|
||||||
|
fileNameStr = fileNameStr.Replace("/", ",");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileNameStr = saveFileName;
|
||||||
|
}
|
||||||
|
input.fileName = fileNameStr;
|
||||||
|
input.folder = floder;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,6 +80,14 @@ namespace JNPF.Common.Core.Manager.Files
|
|||||||
/// <param name="toFilePath">剪切地址.</param>
|
/// <param name="toFilePath">剪切地址.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task MoveFile(string filePath, string toFilePath);
|
Task MoveFile(string filePath, string toFilePath);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 复制文件.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath">源文件地址.</param>
|
||||||
|
/// <param name="toFilePath">剪切地址.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task CopyFile(string filePath, string toFilePath);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -109,5 +117,12 @@ namespace JNPF.Common.Core.Manager.Files
|
|||||||
/// <param name="size"></param>
|
/// <param name="size"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
string GetFileSize(long size);
|
string GetFileSize(long size);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取地址和文件名.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <param name="saveFileName"></param>
|
||||||
|
void GetChunkModel(ChunkModel input, string saveFileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,4 +145,16 @@ public interface IUserManager
|
|||||||
/// <param name="organizeId">组织Id.</param>
|
/// <param name="organizeId">组织Id.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<string>> GetUserOrgRoleIds(string roleIds, string organizeId);
|
Task<List<string>> GetUserOrgRoleIds(string roleIds, string organizeId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是否管理员.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool IsAdmin(string userId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取管理员用户id.
|
||||||
|
/// </summary>
|
||||||
|
string GetAdminUserId();
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,7 @@ using JNPF.DependencyInjection;
|
|||||||
using JNPF.Systems.Entitys.Entity.Permission;
|
using JNPF.Systems.Entitys.Entity.Permission;
|
||||||
using JNPF.Systems.Entitys.Permission;
|
using JNPF.Systems.Entitys.Permission;
|
||||||
using JNPF.Systems.Entitys.System;
|
using JNPF.Systems.Entitys.System;
|
||||||
|
using Mapster;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
@@ -118,7 +119,7 @@ public class UserManager : IUserManager, IScoped
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string ToKen
|
public string ToKen
|
||||||
{
|
{
|
||||||
get => String.IsNullOrEmpty(App.HttpContext?.Request.Headers["Authorization"]) ? App.HttpContext?.Request.Query["token"] : App.HttpContext?.Request.Headers["Authorization"];
|
get => string.IsNullOrEmpty(App.HttpContext?.Request.Headers["Authorization"]) ? App.HttpContext?.Request.Query["token"] : App.HttpContext?.Request.Headers["Authorization"];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -134,7 +135,7 @@ public class UserManager : IUserManager, IScoped
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string TenantId
|
public string TenantId
|
||||||
{
|
{
|
||||||
get => ConnectionConfig.ConfigId;
|
get => ConnectionConfig?.ConfigId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -142,7 +143,7 @@ public class UserManager : IUserManager, IScoped
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string TenantDbName
|
public string TenantDbName
|
||||||
{
|
{
|
||||||
get => ConnectionConfig.ConfigList.Find(it => it.IsMaster.Equals(true)).ServiceName;
|
get => ConnectionConfig?.ConfigList?.Find(it => it.IsMaster.Equals(true)).ServiceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -215,9 +216,11 @@ public class UserManager : IUserManager, IScoped
|
|||||||
{
|
{
|
||||||
UserAgent userAgent = new UserAgent(_httpContext);
|
UserAgent userAgent = new UserAgent(_httpContext);
|
||||||
var data = new UserInfoModel();
|
var data = new UserInfoModel();
|
||||||
|
var userCache = string.Format("{0}:{1}:{2}", TenantId, CommonConst.CACHEKEYUSER, UserId);
|
||||||
|
var userDataScope = await GetUserDataScopeAsync(UserId);
|
||||||
|
|
||||||
var ipAddress = NetHelper.Ip;
|
var ipAddress = NetHelper.Ip;
|
||||||
//var ipAddressName = await NetHelper.GetLocation(ipAddress);
|
//var ipAddressName = await NetHelper.GetLocation(ipAddress);
|
||||||
var userDataScope = await GetUserDataScopeAsync(UserId);
|
|
||||||
var sysConfigInfo = await _repository.AsSugarClient().Queryable<SysConfigEntity>().FirstAsync(s => s.Category.Equals("SysConfig") && s.Key.ToLower().Equals("tokentimeout"));
|
var sysConfigInfo = await _repository.AsSugarClient().Queryable<SysConfigEntity>().FirstAsync(s => s.Category.Equals("SysConfig") && s.Key.ToLower().Equals("tokentimeout"));
|
||||||
data = await _repository.AsQueryable().Where(it => it.Id == UserId)
|
data = await _repository.AsQueryable().Where(it => it.Id == UserId)
|
||||||
.Select(a => new UserInfoModel
|
.Select(a => new UserInfoModel
|
||||||
@@ -246,11 +249,14 @@ public class UserManager : IUserManager, IScoped
|
|||||||
birthday = a.Birthday,
|
birthday = a.Birthday,
|
||||||
systemId = a.SystemId,
|
systemId = a.SystemId,
|
||||||
signImg = SqlFunc.Subqueryable<SignImgEntity>().Where(a => a.CreatorUserId == UserId && a.IsDefault == 1).Select(a => a.SignImg),
|
signImg = SqlFunc.Subqueryable<SignImgEntity>().Where(a => a.CreatorUserId == UserId && a.IsDefault == 1).Select(a => a.SignImg),
|
||||||
|
changePasswordDate = a.ChangePasswordDate,
|
||||||
|
loginTime = DateTime.Now,
|
||||||
}).FirstAsync();
|
}).FirstAsync();
|
||||||
if (data.portalId.IsNullOrWhiteSpace()) data.portalId = string.Empty;
|
if (data.portalId.IsNullOrWhiteSpace()) data.portalId = string.Empty;
|
||||||
if (data != null && data.organizeName.IsNotEmptyOrNull())
|
if (data != null && data.organizeName.IsNotEmptyOrNull())
|
||||||
{
|
{
|
||||||
var orgIdTree = data?.organizeName?.Split(',');
|
var orgIdTree = data?.organizeName?.Split(',');
|
||||||
|
data.organizeIdList = orgIdTree.ToList();
|
||||||
var organizeName = await _repository.AsSugarClient().Queryable<OrganizeEntity>().Where(x => orgIdTree.Contains(x.Id)).OrderBy(x => x.SortCode).OrderBy(x => x.CreatorTime).Select(x => x.FullName).ToListAsync();
|
var organizeName = await _repository.AsSugarClient().Queryable<OrganizeEntity>().Where(x => orgIdTree.Contains(x.Id)).OrderBy(x => x.SortCode).OrderBy(x => x.CreatorTime).Select(x => x.FullName).ToListAsync();
|
||||||
data.organizeName = string.Join("/", organizeName);
|
data.organizeName = string.Join("/", organizeName);
|
||||||
}
|
}
|
||||||
@@ -258,8 +264,6 @@ public class UserManager : IUserManager, IScoped
|
|||||||
{
|
{
|
||||||
data.organizeName = data.departmentName;
|
data.organizeName = data.departmentName;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.loginTime = DateTime.Now;
|
|
||||||
data.prevLogin = (await _repository.AsSugarClient().Queryable<SysConfigEntity>().FirstAsync(x => x.Category.Equals("SysConfig") && x.Key.ToLower().Equals("lastlogintimeswitch"))).Value.ParseToInt();
|
data.prevLogin = (await _repository.AsSugarClient().Queryable<SysConfigEntity>().FirstAsync(x => x.Category.Equals("SysConfig") && x.Key.ToLower().Equals("lastlogintimeswitch"))).Value.ParseToInt();
|
||||||
data.loginIPAddress = ipAddress;
|
data.loginIPAddress = ipAddress;
|
||||||
//data.loginIPAddressName = ipAddressName;
|
//data.loginIPAddressName = ipAddressName;
|
||||||
@@ -288,7 +292,8 @@ public class UserManager : IUserManager, IScoped
|
|||||||
data.tenantDbName = TenantDbName;
|
data.tenantDbName = TenantDbName;
|
||||||
|
|
||||||
// 根据系统配置过期时间自动过期
|
// 根据系统配置过期时间自动过期
|
||||||
await SetUserInfo(string.Format("{0}{1}_{2}", CommonConst.CACHEKEYUSER, TenantId, UserId), data, TimeSpan.FromMinutes(sysConfigInfo.Value.ParseToDouble()));
|
await SetUserInfo(userCache, data, TimeSpan.FromMinutes(sysConfigInfo.Value.ParseToDouble()));
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1583,7 +1588,7 @@ public class UserManager : IUserManager, IScoped
|
|||||||
ids.AddRange(Subsidiary);
|
ids.AddRange(Subsidiary);
|
||||||
for (int i = 0; i < ids.Count; i++)
|
for (int i = 0; i < ids.Count; i++)
|
||||||
{
|
{
|
||||||
if(i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
switch (conditionItem.Logic)
|
switch (conditionItem.Logic)
|
||||||
{
|
{
|
||||||
@@ -1633,7 +1638,7 @@ public class UserManager : IUserManager, IScoped
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(itemMethod.Equals(QueryType.NotEqual) || itemMethod.Equals(QueryType.NotIncluded))
|
if (itemMethod.Equals(QueryType.NotEqual) || itemMethod.Equals(QueryType.NotIncluded))
|
||||||
conditionalList.Add(new { Key = (int)WhereType.And, Value = new { FieldName = itemField, FieldValue = ids[i], ConditionalType = (int)cmodel.ConditionalType } });
|
conditionalList.Add(new { Key = (int)WhereType.And, Value = new { FieldName = itemField, FieldValue = ids[i], ConditionalType = (int)cmodel.ConditionalType } });
|
||||||
else
|
else
|
||||||
conditionalList.Add(new { Key = (int)WhereType.Or, Value = new { FieldName = itemField, FieldValue = ids[i], ConditionalType = (int)cmodel.ConditionalType } });
|
conditionalList.Add(new { Key = (int)WhereType.Or, Value = new { FieldName = itemField, FieldValue = ids[i], ConditionalType = (int)cmodel.ConditionalType } });
|
||||||
@@ -2020,6 +2025,16 @@ public class UserManager : IUserManager, IScoped
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 会否存在用户缓存.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cacheKey"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private async Task<bool> ExistsUserInfo(string cacheKey)
|
||||||
|
{
|
||||||
|
return await _cacheManager.ExistsAsync(cacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 保存用户登录信息.
|
/// 保存用户登录信息.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2031,4 +2046,35 @@ public class UserManager : IUserManager, IScoped
|
|||||||
{
|
{
|
||||||
return await _cacheManager.SetAsync(cacheKey, userInfo, timeSpan);
|
return await _cacheManager.SetAsync(cacheKey, userInfo, timeSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取用户登录信息.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cacheKey">key.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private async Task<UserInfoModel> GetUserInfo(string cacheKey)
|
||||||
|
{
|
||||||
|
return (await _cacheManager.GetAsync(cacheKey)).Adapt<UserInfoModel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是否管理员.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool IsAdmin(string userId)
|
||||||
|
{
|
||||||
|
if (userId == "admin") return true;
|
||||||
|
return _repository.AsSugarClient().Queryable<UserEntity>().Any(x => x.Id == userId && x.Account == "admin" && x.DeleteMark == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取管理员用户id.
|
||||||
|
/// </summary>
|
||||||
|
public string GetAdminUserId()
|
||||||
|
{
|
||||||
|
var user = _repository.AsSugarClient().Queryable<UserEntity>().First(x => x.Account == "admin" && x.DeleteMark == null);
|
||||||
|
if (user.IsNotEmptyOrNull()) return user.Id;
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -12,11 +12,13 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="RabbitMQ.Client" Version="6.4.0" />
|
<PackageReference Include="RabbitMQ.Client" Version="6.4.0" />
|
||||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.0" />
|
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.0" />
|
||||||
|
<PackageReference Include="DotNetCore.Natasha.CSharp" Version="5.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\message\Tnb.Message.Entitys\Tnb.Message.Entitys.csproj" />
|
<ProjectReference Include="..\..\message\Tnb.Message.Entitys\Tnb.Message.Entitys.csproj" />
|
||||||
<ProjectReference Include="..\..\system\Tnb.Systems.Entitys\Tnb.Systems.Entitys.csproj" />
|
<ProjectReference Include="..\..\system\Tnb.Systems.Interfaces\Tnb.Systems.Interfaces.csproj" />
|
||||||
|
<ProjectReference Include="..\..\taskschedule\Tnb.TaskScheduler.Entitys\Tnb.TaskScheduler.Entitys.csproj" />
|
||||||
<ProjectReference Include="..\..\visualdev\Tnb.VisualDev.Entitys\Tnb.VisualDev.Entitys.csproj" />
|
<ProjectReference Include="..\..\visualdev\Tnb.VisualDev.Entitys\Tnb.VisualDev.Entitys.csproj" />
|
||||||
|
|
||||||
<ProjectReference Include="..\Tnb.WebSockets\Tnb.WebSockets.csproj" />
|
<ProjectReference Include="..\Tnb.WebSockets\Tnb.WebSockets.csproj" />
|
||||||
|
|||||||
@@ -28,6 +28,17 @@ public class KeyVariable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 多租户模式.
|
||||||
|
/// </summary>
|
||||||
|
public static string MultiTenancyType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _tenant.MultiTenancyType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 系统文件路径.
|
/// 系统文件路径.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -42,4 +42,9 @@ public class ClaimConst
|
|||||||
/// 单一登录方式(1:后登录踢出先登录 2:同时登录).
|
/// 单一登录方式(1:后登录踢出先登录 2:同时登录).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string SINGLELOGIN = "SingleLogin";
|
public const string SINGLELOGIN = "SingleLogin";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单点登录标识.
|
||||||
|
/// </summary>
|
||||||
|
public const string OnlineTicket = "OnlineTicket";
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@ public class CommonConst
|
|||||||
ContractResolver = new DefaultContractResolver(),
|
ContractResolver = new DefaultContractResolver(),
|
||||||
|
|
||||||
// 设置时区为 UTC
|
// 设置时区为 UTC
|
||||||
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
|
DateTimeZoneHandling = DateTimeZoneHandling.Local,
|
||||||
|
|
||||||
// 格式化json输出的日期格式
|
// 格式化json输出的日期格式
|
||||||
DateFormatString = "yyyy-MM-dd HH:mm:ss",
|
DateFormatString = "yyyy-MM-dd HH:mm:ss",
|
||||||
@@ -41,7 +41,7 @@ public class CommonConst
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用户缓存.
|
/// 用户缓存.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string CACHEKEYUSER = "user_";
|
public const string CACHEKEYUSER = "jnpf:permission:user";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 菜单缓存.
|
/// 菜单缓存.
|
||||||
@@ -102,4 +102,19 @@ public class CommonConst
|
|||||||
/// 第三方登录 票据缓存key.
|
/// 第三方登录 票据缓存key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string PARAMS_JNPF_TICKET = "jnpf_ticket";
|
public const string PARAMS_JNPF_TICKET = "jnpf_ticket";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cas Key.
|
||||||
|
/// </summary>
|
||||||
|
public const string CAS_Ticket = "ticket";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Code.
|
||||||
|
/// </summary>
|
||||||
|
public const string Code = "code";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 外链密码开关(1:开 , 0:关).
|
||||||
|
/// </summary>
|
||||||
|
public const int OnlineDevData_State_Enable = 1;
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ public abstract class CDEntityBase : EntityBase<string>, ICreatorTime, IDeleteTi
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void Creator()
|
public virtual void Creator()
|
||||||
{
|
{
|
||||||
var userId = App.User.FindFirst(ClaimConst.CLAINMUSERID)?.Value;
|
var userId = App.User?.FindFirst(ClaimConst.CLAINMUSERID)?.Value;
|
||||||
this.CreatorTime = DateTime.Now;
|
this.CreatorTime = DateTime.Now;
|
||||||
this.Id = SnowflakeIdHelper.NextId();
|
this.Id = SnowflakeIdHelper.NextId();
|
||||||
this.EnabledMark = this.EnabledMark == null ? 1 : this.EnabledMark;
|
this.EnabledMark = this.EnabledMark == null ? 1 : this.EnabledMark;
|
||||||
@@ -67,7 +67,7 @@ public abstract class CDEntityBase : EntityBase<string>, ICreatorTime, IDeleteTi
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void Create()
|
public virtual void Create()
|
||||||
{
|
{
|
||||||
var userId = App.User.FindFirst(ClaimConst.CLAINMUSERID)?.Value;
|
var userId = App.User?.FindFirst(ClaimConst.CLAINMUSERID)?.Value;
|
||||||
this.CreatorTime = DateTime.Now;
|
this.CreatorTime = DateTime.Now;
|
||||||
this.Id = this.Id == null ? SnowflakeIdHelper.NextId() : this.Id;
|
this.Id = this.Id == null ? SnowflakeIdHelper.NextId() : this.Id;
|
||||||
this.EnabledMark = this.EnabledMark == null ? 1 : this.EnabledMark;
|
this.EnabledMark = this.EnabledMark == null ? 1 : this.EnabledMark;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using JNPF.Common.Const;
|
using JNPF.Common.Const;
|
||||||
using JNPF.Common.Security;
|
using JNPF.Common.Security;
|
||||||
using JNPF.DependencyInjection;
|
using JNPF.DependencyInjection;
|
||||||
|
using JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
|
||||||
namespace JNPF.Common.Contracts;
|
namespace JNPF.Common.Contracts;
|
||||||
@@ -28,7 +29,7 @@ public abstract class CEntityBase : EntityBase<string>, ICreatorTime
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void Creator()
|
public virtual void Creator()
|
||||||
{
|
{
|
||||||
var userId = App.User.FindFirst(ClaimConst.CLAINMUSERID)?.Value;
|
var userId = App.User?.FindFirst(ClaimConst.CLAINMUSERID)?.Value;
|
||||||
this.CreatorTime = DateTime.Now;
|
this.CreatorTime = DateTime.Now;
|
||||||
this.Id = SnowflakeIdHelper.NextId();
|
this.Id = SnowflakeIdHelper.NextId();
|
||||||
if (!string.IsNullOrEmpty(userId))
|
if (!string.IsNullOrEmpty(userId))
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public abstract class CLDEntityBase : EntityBase<string>, ICreatorTime, IDeleteT
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void Creator()
|
public virtual void Creator()
|
||||||
{
|
{
|
||||||
var userId = App.User.FindFirst(ClaimConst.CLAINMUSERID)?.Value;
|
var userId = App.User?.FindFirst(ClaimConst.CLAINMUSERID)?.Value;
|
||||||
this.CreatorTime = DateTime.Now;
|
this.CreatorTime = DateTime.Now;
|
||||||
this.Id = SnowflakeIdHelper.NextId();
|
this.Id = SnowflakeIdHelper.NextId();
|
||||||
this.EnabledMark = this.EnabledMark == null ? 1 : this.EnabledMark;
|
this.EnabledMark = this.EnabledMark == null ? 1 : this.EnabledMark;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class CLEntityBase : EntityBase<string>, ICreatorTime
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void Creator()
|
public virtual void Creator()
|
||||||
{
|
{
|
||||||
var userId = App.User.FindFirst(ClaimConst.CLAINMUSERID)?.Value;
|
var userId = App.User?.FindFirst(ClaimConst.CLAINMUSERID)?.Value;
|
||||||
this.CreatorTime = DateTime.Now;
|
this.CreatorTime = DateTime.Now;
|
||||||
this.Id = SnowflakeIdHelper.NextId();
|
this.Id = SnowflakeIdHelper.NextId();
|
||||||
if (!string.IsNullOrEmpty(userId))
|
if (!string.IsNullOrEmpty(userId))
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using JNPF.DependencyInjection;
|
using JNPF.DependencyInjection;
|
||||||
|
using JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
|
||||||
namespace JNPF.Common.Contracts;
|
namespace JNPF.Common.Contracts;
|
||||||
@@ -7,7 +8,7 @@ namespace JNPF.Common.Contracts;
|
|||||||
/// 实体类基类.
|
/// 实体类基类.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SuppressSniffer]
|
[SuppressSniffer]
|
||||||
public abstract class EntityBase<TKey> : IEntity<TKey>
|
public abstract class EntityBase<TKey> : ITenantFilter, IEntity<TKey>
|
||||||
where TKey : IEquatable<TKey>
|
where TKey : IEquatable<TKey>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -15,4 +16,10 @@ public abstract class EntityBase<TKey> : IEntity<TKey>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(ColumnName = "F_Id", ColumnDescription = "主键", IsPrimaryKey = true)]
|
[SugarColumn(ColumnName = "F_Id", ColumnDescription = "主键", IsPrimaryKey = true)]
|
||||||
public TKey Id { get; set; }
|
public TKey Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取或设置 租户id.
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(ColumnName = "F_TenantId", ColumnDescription = "租户id")]
|
||||||
|
public string TenantId { get; set; }
|
||||||
}
|
}
|
||||||
@@ -670,6 +670,11 @@ public enum ErrorCode
|
|||||||
[ErrorCodeItemMetadata("第三方登录未配置!")]
|
[ErrorCodeItemMetadata("第三方登录未配置!")]
|
||||||
D5025,
|
D5025,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 修改失败,新建密码不能与旧密码一样.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("修改失败,新建密码不能与旧密码一样")]
|
||||||
|
D5026,
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 岗位 6
|
#region 岗位 6
|
||||||
@@ -968,6 +973,11 @@ public enum ErrorCode
|
|||||||
[ErrorCodeItemMetadata("验证码限定范围:3 - 6位")]
|
[ErrorCodeItemMetadata("验证码限定范围:3 - 6位")]
|
||||||
D9009,
|
D9009,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 打印模板不存在.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("打印模板不存在")]
|
||||||
|
D9010,
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 单据规则 10
|
#region 单据规则 10
|
||||||
@@ -1107,12 +1117,28 @@ public enum ErrorCode
|
|||||||
D1417,
|
D1417,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 该功能不存在,可能已被删除.
|
/// 密码错误.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ErrorCodeItemMetadata("该功能( id: {0} )不存在,可能已被删除")]
|
[ErrorCodeItemMetadata("密码错误")]
|
||||||
D1418,
|
D1418,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 缺少租户信息.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("缺少租户信息")]
|
||||||
|
D1419,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 无效链接.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("无效链接")]
|
||||||
|
D1420,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发布失败,流程未设计.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("发布失败,流程未设计")]
|
||||||
|
D1421,
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 数据建模 15
|
#region 数据建模 15
|
||||||
@@ -1201,6 +1227,18 @@ public enum ErrorCode
|
|||||||
[ErrorCodeItemMetadata("Sql不能为空")]
|
[ErrorCodeItemMetadata("Sql不能为空")]
|
||||||
D1513,
|
D1513,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表名超过规定长度.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("表名超过规定长度")]
|
||||||
|
D1514,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列名超过规定长度.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("列名超过规定长度")]
|
||||||
|
D1515,
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 角色 16
|
#region 角色 16
|
||||||
@@ -1425,9 +1463,9 @@ public enum ErrorCode
|
|||||||
D2104,
|
D2104,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 表缺失流程Id.
|
/// 表缺失流程Id字段.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ErrorCodeItemMetadata("表缺失流程Id")]
|
[ErrorCodeItemMetadata("表缺失流程Id字段:F_FLowId")]
|
||||||
D2105,
|
D2105,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1454,6 +1492,12 @@ public enum ErrorCode
|
|||||||
[ErrorCodeItemMetadata("模板主键策略与表主键策略不同")]
|
[ErrorCodeItemMetadata("模板主键策略与表主键策略不同")]
|
||||||
D2109,
|
D2109,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表缺失逻辑删除字段.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("表缺失逻辑删除字段:F_DeleteMark")]
|
||||||
|
D2110,
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 大屏 22
|
#region 大屏 22
|
||||||
@@ -1772,11 +1816,46 @@ public enum ErrorCode
|
|||||||
WF0045,
|
WF0045,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 退回至您的审批,不能再撤回审批.
|
/// 此流程已被挂起,无法操作!.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ErrorCodeItemMetadata("退回至您的审批,不能再撤回审批!")]
|
[ErrorCodeItemMetadata("流程处于挂起状态,不可操作!")]
|
||||||
WF0046,
|
WF0046,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// {0}流程已被挂起,无法操作!.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("{0}流程已被挂起不能删除!")]
|
||||||
|
WF0047,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 退回至您的审批,不能再撤回审批.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("退回至您的审批,不能再撤回审批!")]
|
||||||
|
WF0048,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 您没有该流程的发起权限.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("您没有该流程的发起权限")]
|
||||||
|
WF0049,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下一节点已审批,不能撤回!
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("下一节点已审批,不能撤回!")]
|
||||||
|
WF0050,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 流程已撤回,不能重复操作!.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("流程已撤回,不能重复操作!")]
|
||||||
|
WF0051,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 该流程由在线开发生成的,无法直接删除,请在功能设计中删除相关功能!.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("该流程由在线开发生成的,无法直接删除,请在功能设计中删除相关功能!")]
|
||||||
|
WF0052,
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 扩展 Ex
|
#region 扩展 Ex
|
||||||
@@ -2018,9 +2097,9 @@ public enum ErrorCode
|
|||||||
COM1015,
|
COM1015,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 未找到流程引擎.
|
/// 流程未设计,请先设计流程.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ErrorCodeItemMetadata("未找到流程引擎")]
|
[ErrorCodeItemMetadata("流程未设计,请先设计流程")]
|
||||||
COM1016,
|
COM1016,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -2028,5 +2107,23 @@ public enum ErrorCode
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[ErrorCodeItemMetadata("该功能配置的流程处于停用状态")]
|
[ErrorCodeItemMetadata("该功能配置的流程处于停用状态")]
|
||||||
COM1017,
|
COM1017,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 该功能配置的流程处于停用状态.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("接口请求失败")]
|
||||||
|
COM1018,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 该功能未导入流程表单!.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("该功能未导入流程表单!")]
|
||||||
|
COM1019,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 接口数据异常!.
|
||||||
|
/// </summary>
|
||||||
|
[ErrorCodeItemMetadata("接口数据异常!")]
|
||||||
|
COM1020,
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Tnb.Common.Enums
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 工艺路线类型
|
|
||||||
/// </summary>
|
|
||||||
public enum RouteType
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 标准途程
|
|
||||||
/// </summary>
|
|
||||||
[Description("标准途程")]
|
|
||||||
Standard=1,
|
|
||||||
/// <summary>
|
|
||||||
/// 返工途程
|
|
||||||
/// </summary>
|
|
||||||
[Description("返工途程")]
|
|
||||||
Rework=2,
|
|
||||||
/// <summary>
|
|
||||||
/// 试制途程
|
|
||||||
/// </summary>
|
|
||||||
[Description("试制途程")]
|
|
||||||
Trial=4,
|
|
||||||
/// <summary>
|
|
||||||
/// 返修途程
|
|
||||||
/// </summary>
|
|
||||||
[Description("返修途程")]
|
|
||||||
RMA =8,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -31,7 +31,7 @@ public static class BooleanExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static bool? GetBool(this object data)
|
private static bool? GetBool(this object data)
|
||||||
{
|
{
|
||||||
switch (data.ToString()?.Trim().ToLower())
|
switch (data.ToString().Trim().ToLower())
|
||||||
{
|
{
|
||||||
case "0":
|
case "0":
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public static class DictionaryExtensions
|
|||||||
/// <param name="dictionary">要操作的字典.</param>
|
/// <param name="dictionary">要操作的字典.</param>
|
||||||
/// <param name="key">指定键名.</param>
|
/// <param name="key">指定键名.</param>
|
||||||
/// <returns>获取到的值.</returns>
|
/// <returns>获取到的值.</returns>
|
||||||
public static TValue? GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
|
public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
|
||||||
{
|
{
|
||||||
return dictionary.TryGetValue(key, out TValue value) ? value : default(TValue);
|
return dictionary.TryGetValue(key, out TValue value) ? value : default(TValue);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -693,4 +693,25 @@ public static partial class Extensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region List
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 嵌套List解析
|
||||||
|
/// 仅限于列表查询条件多选.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="list"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static List<string> ParseToNestedList(this List<List<string>> list)
|
||||||
|
{
|
||||||
|
List<string> result = new List<string>();
|
||||||
|
if (list != null && list.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var item in list)
|
||||||
|
result.Add(item.Last());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ public static class RandomExtensions
|
|||||||
public static T NextItem<T>(this Random random, T[] items)
|
public static T NextItem<T>(this Random random, T[] items)
|
||||||
{
|
{
|
||||||
if (items == null || items.Length == 0)
|
if (items == null || items.Length == 0)
|
||||||
return default(T)!;
|
return default(T);
|
||||||
|
|
||||||
return items[random.Next(items.Length)];
|
return items[random.Next(items.Length)];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -354,7 +354,7 @@ public static class StringExtensions
|
|||||||
/// 指示指定的字符串是 null、空或者仅由空白字符组成.
|
/// 指示指定的字符串是 null、空或者仅由空白字符组成.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DebuggerStepThrough]
|
[DebuggerStepThrough]
|
||||||
public static bool IsNullOrWhiteSpace(this string value)
|
public static bool IsNullOrWhiteSpace(this string? value)
|
||||||
{
|
{
|
||||||
return string.IsNullOrWhiteSpace(value);
|
return string.IsNullOrWhiteSpace(value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,4 +41,20 @@ public class CodeGenAuthorizeModuleResource
|
|||||||
/// 权限条件.
|
/// 权限条件.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<object> conditionalModel { get; set; }
|
public List<object> conditionalModel { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 代码生成 数据过滤.
|
||||||
|
/// </summary>
|
||||||
|
public class CodeGenDataRuleModuleResourceModel : CodeGenAuthorizeModuleResourceModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 请求类型 pc 和 app.
|
||||||
|
/// </summary>
|
||||||
|
public string UserOrigin { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 权限条件 json.
|
||||||
|
/// </summary>
|
||||||
|
public string conditionalModelJson { get; set; }
|
||||||
}
|
}
|
||||||
@@ -86,4 +86,19 @@ public class ChunkModel
|
|||||||
/// 文件.
|
/// 文件.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IFormFile file { get; set; }
|
public IFormFile file { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 路径类型 defaultPath(默认路径) selfPath(自定义路径).
|
||||||
|
/// </summary>
|
||||||
|
public string pathType { get; set; } = "defaultPath";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否用户存储(0否1是).
|
||||||
|
/// </summary>
|
||||||
|
public string isAccount { get; set; } = "0";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 自定义文件夹路径.
|
||||||
|
/// </summary>
|
||||||
|
public string folder { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,4 +32,9 @@ public class FileControlsModel
|
|||||||
/// 文件后缀.
|
/// 文件后缀.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? fileExtension { get; set; }
|
public string? fileExtension { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件名称.
|
||||||
|
/// </summary>
|
||||||
|
public string? fileName { get; set; }
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,8 @@ namespace JNPF.Common.Models.NPOI;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Excel导出列名
|
/// Excel导出列名
|
||||||
/// 版 本:V3.0.0
|
/// 版 本:V3.0.0
|
||||||
/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
|
/// 版 权:引迈信息技术有限公司(https://www.jnpfsoft.com)
|
||||||
|
/// 作 者:JNPF开发平台组
|
||||||
/// 日 期:2017.03.09.
|
/// 日 期:2017.03.09.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SuppressSniffer]
|
[SuppressSniffer]
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ namespace JNPF.Common.Models.NPOI;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Excel导出配置
|
/// Excel导出配置
|
||||||
/// 版 本:V3.0.0
|
/// 版 本:V3.0.0
|
||||||
/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
|
/// 版 权:引迈信息技术有限公司(https://www.jnpfsoft.com)
|
||||||
|
/// 作 者:JNPF开发平台组
|
||||||
/// 日 期:2017.03.09.
|
/// 日 期:2017.03.09.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SuppressSniffer]
|
[SuppressSniffer]
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ namespace JNPF.Common.Models.NPOI;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Excel导出模板
|
/// Excel导出模板
|
||||||
/// 版 本:V3.0.0
|
/// 版 本:V3.0.0
|
||||||
/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
|
/// 版 权:引迈信息技术有限公司(https://www.jnpfsoft.com)
|
||||||
|
/// 作 者:JNPF开发平台组
|
||||||
/// 日 期:2017.03.09.
|
/// 日 期:2017.03.09.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SuppressSniffer]
|
[SuppressSniffer]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace JNPF.Common.Models.User
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 登录者信息
|
/// 登录者信息
|
||||||
/// 版 本:V3.2.0
|
/// 版 本:V3.2.0
|
||||||
/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
|
/// 版 权:引迈信息技术有限公司(https://www.jnpfsoft.com)
|
||||||
/// 作 者:JNPF开发平台组.
|
/// 作 者:JNPF开发平台组.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SuppressSniffer]
|
[SuppressSniffer]
|
||||||
@@ -51,6 +51,11 @@ namespace JNPF.Common.Models.User
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string organizeId { get; set; }
|
public string organizeId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 所属组织 Id 树.
|
||||||
|
/// </summary>
|
||||||
|
public List<string> organizeIdList { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 组织名称.
|
/// 组织名称.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -225,6 +230,11 @@ namespace JNPF.Common.Models.User
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string signImg { get; set; }
|
public string signImg { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认签名.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? changePasswordDate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 系统集合.
|
/// 系统集合.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ public class UserOnlineModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string token { get; set; }
|
public string token { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单点登录标识.
|
||||||
|
/// </summary>
|
||||||
|
public string onlineTicket { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否移动端.
|
/// 是否移动端.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -46,5 +46,10 @@
|
|||||||
/// 流程类型.
|
/// 流程类型.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? type { get; set; }
|
public int? type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 所属流程名称.
|
||||||
|
/// </summary>
|
||||||
|
public string? flowName { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
103
common/Tnb.Common/Options/OauthOptions.cs
Normal file
103
common/Tnb.Common/Options/OauthOptions.cs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
using Aspose.Cells;
|
||||||
|
using JNPF.Common.Enums;
|
||||||
|
using JNPF.ConfigurableOptions;
|
||||||
|
using NPOI.SS.Formula.Functions;
|
||||||
|
|
||||||
|
namespace JNPF.Common.Options;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单点登录配置.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class OauthOptions : IConfigurableOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 是否启用.
|
||||||
|
/// </summary>
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前端登录页面访问登录接口进行单点登录页面跳转, 需要与身份管理系统中的 JNPF-Auth2、JNPF-CAS中的认证地址一致.
|
||||||
|
/// </summary>
|
||||||
|
public string LoginPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从单点登录中心直接访问JNPF时登录成功后跳转的前端页面.
|
||||||
|
/// </summary>
|
||||||
|
public string SucessFrontUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认接口.
|
||||||
|
/// </summary>
|
||||||
|
public string DefaultSSO { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 缓存过期时间 / 分钟.
|
||||||
|
/// </summary>
|
||||||
|
public int TicketTimeout { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否前端输出消息.
|
||||||
|
/// </summary>
|
||||||
|
public bool TicketOutMessage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 登录模式.
|
||||||
|
/// </summary>
|
||||||
|
public SSO SSO { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户推送.
|
||||||
|
/// </summary>
|
||||||
|
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; }
|
||||||
|
|
||||||
|
}
|
||||||
@@ -54,7 +54,7 @@ public static class CodeGenExportDataHelper
|
|||||||
|
|
||||||
var len = rowChildDatas.Select(x => x.Value.Count()).OrderByDescending(x => x).FirstOrDefault();
|
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++)
|
for (int i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -160,6 +160,79 @@ public static class CodeGenHelper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据列表生成树形表格.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="realList">数据列表.</param>
|
||||||
|
/// <param name="parentField">树形父级字段.</param>
|
||||||
|
/// <param name="treeShowField">树形显示字段.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static List<Dictionary<string, object>> GetTreeList(List<Dictionary<string, object>> realList, string parentField, string treeShowField)
|
||||||
|
{
|
||||||
|
var res = new List<Dictionary<string, object>>();
|
||||||
|
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<Dictionary<string, object>> allList, Dictionary<string, object> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据集合捞取所有子集id.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="allList">key : 主键Id , value : 父亲Id.</param>
|
||||||
|
/// <param name="currentId">当前id.</param>
|
||||||
|
/// <param name="resList">res.</param>
|
||||||
|
public static List<string> GetChildIdList(Dictionary<string, string> allList, string currentId, List<string> resList)
|
||||||
|
{
|
||||||
|
if (resList == null) resList = new List<string>() { 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;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取排序真实字段.
|
/// 获取排序真实字段.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -190,7 +263,7 @@ public static class CodeGenHelper
|
|||||||
field = entityInfo.Columns.Find(it => it.PropertyName.Equals(sort.ToUpperCase()))?.DbColumnName;
|
field = entityInfo.Columns.Find(it => it.PropertyName.Equals(sort.ToUpperCase()))?.DbColumnName;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return string.IsNullOrEmpty(field) ? "" : field;
|
return string.IsNullOrEmpty(field) ? null : field;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using JNPF.Common.Helper;
|
|
||||||
using JNPF.Common.Models.NPOI;
|
using JNPF.Common.Models.NPOI;
|
||||||
using JNPF.DependencyInjection;
|
using JNPF.DependencyInjection;
|
||||||
using NPOI.HPSF;
|
using NPOI.HPSF;
|
||||||
@@ -9,8 +8,6 @@ using NPOI.HSSF.UserModel;
|
|||||||
using NPOI.SS.UserModel;
|
using NPOI.SS.UserModel;
|
||||||
using NPOI.SS.Util;
|
using NPOI.SS.Util;
|
||||||
using NPOI.XSSF.UserModel;
|
using NPOI.XSSF.UserModel;
|
||||||
using Spire.Doc;
|
|
||||||
using static Microsoft.AspNetCore.Razor.Language.TagHelperMetadata;
|
|
||||||
|
|
||||||
namespace JNPF.Common.Security;
|
namespace JNPF.Common.Security;
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,17 @@ public static class JsonHelper
|
|||||||
return _jsonSerializer.Deserialize<T>(json);
|
return _jsonSerializer.Deserialize<T>(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// JSON 字符串转 Object.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">动态类型.</typeparam>
|
||||||
|
/// <param name="json">对象.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static T ToObjectOld<T>(this string json)
|
||||||
|
{
|
||||||
|
return _ = JsonConvert.DeserializeObject<T>(json) ?? default(T);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// JSON 字符串转 Object.
|
/// JSON 字符串转 Object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ public static class NetHelper
|
|||||||
string result = string.Empty;
|
string result = string.Empty;
|
||||||
if (App.HttpContext != null)
|
if (App.HttpContext != null)
|
||||||
result = GetWebClientIp();
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -4,11 +4,11 @@ namespace JNPF.Common.Security;
|
|||||||
|
|
||||||
public static class XmlHelper
|
public static class XmlHelper
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 反序列化
|
/// 反序列化.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="type">类型</param>
|
/// <param name="type">类型.</param>
|
||||||
/// <param name="xml">XML字符串</param>
|
/// <param name="xml">XML字符串.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static object Deserialize(Type type, string xml)
|
public static object Deserialize(Type type, string xml)
|
||||||
{
|
{
|
||||||
@@ -19,13 +19,12 @@ public static class XmlHelper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 反序列化
|
/// 反序列化.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="type"></param>
|
/// <param name="type">类型.</param>
|
||||||
/// <param name="xml"></param>
|
/// <param name="stream">XML流.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
|
||||||
public static object Deserialize(Type type, Stream stream)
|
public static object Deserialize(Type type, Stream stream)
|
||||||
{
|
{
|
||||||
XmlSerializer xmldes = new XmlSerializer(type);
|
XmlSerializer xmldes = new XmlSerializer(type);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using JNPF.DataEncryption;
|
using JNPF;
|
||||||
|
using JNPF.DataEncryption;
|
||||||
using JNPF.Extras.DatabaseAccessor.SqlSugar;
|
using JNPF.Extras.DatabaseAccessor.SqlSugar;
|
||||||
using JNPF.Extras.DatabaseAccessor.SqlSugar.Extensions;
|
using JNPF.Extras.DatabaseAccessor.SqlSugar.Extensions;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
@@ -11,8 +12,7 @@ namespace SqlSugar;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class JNPFTenantExtensions
|
public class JNPFTenantExtensions
|
||||||
{
|
{
|
||||||
//public static IConfiguration _config { get; set; }
|
public static IConfiguration _config { get; set; }
|
||||||
private static ConnectionStringsOptions _connOpt { get; }
|
|
||||||
|
|
||||||
public static string skey = "Vl4WTqna9aZCgswjieIP";
|
public static string skey = "Vl4WTqna9aZCgswjieIP";
|
||||||
|
|
||||||
@@ -21,8 +21,7 @@ public class JNPFTenantExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
static JNPFTenantExtensions()
|
static JNPFTenantExtensions()
|
||||||
{
|
{
|
||||||
var config = new ConfigurationBuilder().AddJsonFile("Configurations/ConnectionStrings.json", true, true).Build();
|
_config = new ConfigurationBuilder().Add(new JsonConfigurationSource { Path = "Configurations/ConnectionStrings.json", ReloadOnChange = true }).Build();
|
||||||
_connOpt = config.GetSection("ConnectionStrings").Get<ConnectionStringsOptions>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -33,14 +32,15 @@ public class JNPFTenantExtensions
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ConnectionConfigOptions GetLinkToOrdinary(string configId, string tableName)
|
public static ConnectionConfigOptions GetLinkToOrdinary(string configId, string tableName)
|
||||||
{
|
{
|
||||||
|
ConnectionStringsOptions conn = App.GetConfig<ConnectionStringsOptions>("ConnectionStrings", true);
|
||||||
|
|
||||||
List<DBConnectionConfig> configList = new List<DBConnectionConfig>();
|
List<DBConnectionConfig> configList = new List<DBConnectionConfig>();
|
||||||
var connStr = string.Format(_connOpt.DefaultConnection, _connOpt.Host, _connOpt.Port, _connOpt.DBName, _connOpt.UserName, _connOpt.Password);
|
|
||||||
configList.Add(new DBConnectionConfig()
|
configList.Add(new DBConnectionConfig()
|
||||||
{
|
{
|
||||||
IsMaster = true,
|
IsMaster = true,
|
||||||
ServiceName = tableName,
|
ServiceName = tableName,
|
||||||
dbType = ToDbType(_connOpt.DBType),
|
dbType = (DbType)Enum.Parse(typeof(DbType), conn.DBType),
|
||||||
connectionStr = DESCEncryption.Encrypt(connStr, skey)
|
connectionStr = DESCEncryption.Encrypt(conn.ConnectString, skey)
|
||||||
});
|
});
|
||||||
return new ConnectionConfigOptions()
|
return new ConnectionConfigOptions()
|
||||||
{
|
{
|
||||||
|
|||||||
15
common/Tnb.SqlSugar/Models/ITenantFilter.cs
Normal file
15
common/Tnb.SqlSugar/Models/ITenantFilter.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using SqlSugar;
|
||||||
|
|
||||||
|
namespace JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实体类基类.
|
||||||
|
/// </summary>
|
||||||
|
public interface ITenantFilter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户id.
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(ColumnName = "F_TenantId", ColumnDescription = "租户id")]
|
||||||
|
string TenantId { get; set; }
|
||||||
|
}
|
||||||
@@ -46,4 +46,6 @@ public sealed class ConnectionStringsOptions : IConfigurableOptions
|
|||||||
/// 默认数据库连接字符串.
|
/// 默认数据库连接字符串.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string DefaultConnection { get; set; }
|
public string DefaultConnection { get; set; }
|
||||||
|
|
||||||
|
public string ConnectString { get { return string.Format(DefaultConnection, Host, Port, DBName, UserName, Password); } }
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,11 @@ public sealed class TenantOptions : IConfigurableOptions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool MultiTenancy { get; set; }
|
public bool MultiTenancy { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据隔离类型 SCHEMA:库隔离 COLUMN:字段隔离.
|
||||||
|
/// </summary>
|
||||||
|
public string MultiTenancyType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 多租户数据接口.
|
/// 多租户数据接口.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
using JNPF;
|
using JNPF;
|
||||||
using JNPF.DataEncryption;
|
using JNPF.DataEncryption;
|
||||||
|
using JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
|
||||||
using JNPF.FriendlyException;
|
using JNPF.FriendlyException;
|
||||||
using JNPF.JsonSerialization;
|
using JNPF.JsonSerialization;
|
||||||
using JNPF.Logging;
|
using JNPF.Logging;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace SqlSugar;
|
namespace SqlSugar;
|
||||||
|
|
||||||
@@ -16,95 +16,98 @@ namespace SqlSugar;
|
|||||||
public partial class SqlSugarRepository<TEntity> : SimpleClient<TEntity>, ISqlSugarRepository<TEntity>
|
public partial class SqlSugarRepository<TEntity> : SimpleClient<TEntity>, ISqlSugarRepository<TEntity>
|
||||||
where TEntity : class, new()
|
where TEntity : class, new()
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造函数
|
/// 构造函数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
public SqlSugarRepository(ISqlSugarClient context = null) : base(context)
|
public SqlSugarRepository(ISqlSugarClient context = null) : base(context)
|
||||||
{
|
|
||||||
// 获取数据库连接选项
|
|
||||||
ConnectionStringsOptions connectionStrings = App.GetConfig<ConnectionStringsOptions>("ConnectionStrings", true);
|
|
||||||
|
|
||||||
// 获取多租户选项
|
|
||||||
TenantOptions tenant = App.GetConfig<TenantOptions>("Tenant", true);
|
|
||||||
var httpContext = App.HttpContext;
|
|
||||||
|
|
||||||
base.Context = (SqlSugarScope)context;
|
|
||||||
|
|
||||||
string tenantId = connectionStrings.ConfigId;
|
|
||||||
|
|
||||||
if (httpContext?.GetEndpoint()?.Metadata?.GetMetadata<AllowAnonymousAttribute>() == null || !string.IsNullOrEmpty(httpContext?.Request.Query["token"]))
|
|
||||||
{
|
{
|
||||||
if (tenant.MultiTenancy && httpContext != null)
|
// 获取数据库连接选项
|
||||||
{
|
ConnectionStringsOptions connectionStrings = App.GetConfig<ConnectionStringsOptions>("ConnectionStrings", true);
|
||||||
var connectionConfig = new ConnectionConfigOptions();
|
|
||||||
if (httpContext.Request.Headers.ContainsKey("Authorization"))
|
// 获取多租户选项
|
||||||
|
TenantOptions tenant = App.GetConfig<TenantOptions>("Tenant", true);
|
||||||
|
var httpContext = App.HttpContext;
|
||||||
|
|
||||||
|
base.Context = (SqlSugarScope)context;
|
||||||
|
|
||||||
|
string tenantId = connectionStrings.ConfigId;
|
||||||
|
string tenantDbName = string.Empty;
|
||||||
|
|
||||||
|
if (httpContext?.GetEndpoint()?.Metadata?.GetMetadata<AllowAnonymousAttribute>() == null)
|
||||||
{
|
{
|
||||||
connectionConfig = JSON.Deserialize<ConnectionConfigOptions>(httpContext?.User.FindFirst("ConnectionConfig")?.Value);
|
if (tenant.MultiTenancy && httpContext != null)
|
||||||
tenantId = connectionConfig.ConfigId;
|
{
|
||||||
|
var connectionConfig = JSON.Deserialize<ConnectionConfigOptions>(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;
|
base.Context.QueryFilter.AddTableFilter<ITenantFilter>(it => it.TenantId == tenantDbName);
|
||||||
var claims = JWTEncryption.ReadJwtToken(token.Replace("Bearer ", "").Replace("bearer ", ""))?.Claims;
|
base.Context.Aop.DataExecuting = (oldValue, entityInfo) =>
|
||||||
connectionConfig = JSON.Deserialize<ConnectionConfigOptions>(claims.FirstOrDefault(e => e.Type == "ConnectionConfig").Value);
|
{
|
||||||
tenantId = connectionConfig.ConfigId;
|
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));
|
var oldColor = Console.ForegroundColor;
|
||||||
}
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
base.Context = base.Context.AsTenant().GetConnectionScope(connectionConfig.ConfigId);
|
var finalSql = UtilMethods.GetSqlString(Context.CurrentConnectionConfig.DbType, sql, pars);
|
||||||
|
Console.WriteLine($"【{DateTime.Now.ToString("HH:mm:ss.fff")}——SQL执行完成】{Context.Ado.SqlExecutionTime.TotalMilliseconds} ms");
|
||||||
if (!base.Context.Ado.IsValidConnection())
|
Console.WriteLine(finalSql);
|
||||||
{
|
Console.ForegroundColor = oldColor;
|
||||||
throw Oops.Oh("数据库连接错误");
|
if (Context.Ado.SqlExecutionTime.TotalMilliseconds > 3000)
|
||||||
}
|
{
|
||||||
}
|
Log.Warning($"慢查询: {Context.Ado.SqlExecutionTime.TotalMilliseconds}ms, SQL: " + finalSql);
|
||||||
else
|
}
|
||||||
{
|
Console.WriteLine();
|
||||||
base.Context = base.Context.AsTenant().GetConnectionScope(tenantId);
|
//App.PrintToMiniProfiler("SqlSugar", "Info", sql + "\r\n" + base.Context.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置超时时间
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
return new KeyValuePair<string, SugarParameter[]>(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<string, SugarParameter[]>(sql, pars);
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -18,8 +18,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.73" />
|
<PackageReference Include="SqlSugarCore" Version="5.1.4.77" />
|
||||||
<PackageReference Include="Tnb.Core" Version="2023.3.24.1010" />
|
<PackageReference Include="Tnb.Core" Version="2023.5.25.958" />
|
||||||
<!--<ProjectReference Include="..\..\..\Tnb.Core\Tnb.Core\Tnb.Core.csproj" />-->
|
<!--<ProjectReference Include="..\..\..\Tnb.Core\Tnb.Core\Tnb.Core.csproj" />-->
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,11 @@ public class WebSocketClient
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public LoginMethod SingleLogin { get; set; }
|
public LoginMethod SingleLogin { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单点登录标识.
|
||||||
|
/// </summary>
|
||||||
|
public string onlineTicket { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// token.
|
/// token.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -47,4 +47,19 @@ public class DocumentListOutput
|
|||||||
/// 父级Id.
|
/// 父级Id.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? parentId { get; set; }
|
public string? parentId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文档下载地址.
|
||||||
|
/// </summary>
|
||||||
|
public string? uploaderUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件路径.
|
||||||
|
/// </summary>
|
||||||
|
public string? filePath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否支持预览.
|
||||||
|
/// </summary>
|
||||||
|
public string? isPreview { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,17 +87,17 @@ public class ProductCrInput
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 让利金额.
|
/// 让利金额.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal partPrice { get; set; }
|
public decimal? partPrice { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 优惠金额.
|
/// 优惠金额.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal reducedPrice { get; set; }
|
public decimal? reducedPrice { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 折后金额.
|
/// 折后金额.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal discountPrice { get; set; }
|
public decimal? discountPrice { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 备注.
|
/// 备注.
|
||||||
|
|||||||
@@ -92,17 +92,17 @@ public class ProductInfoOutput
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 让利金额.
|
/// 让利金额.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal partPrice { get; set; }
|
public decimal? partPrice { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 优惠金额.
|
/// 优惠金额.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal reducedPrice { get; set; }
|
public decimal? reducedPrice { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 折后金额.
|
/// 折后金额.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal discountPrice { get; set; }
|
public decimal? discountPrice { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 备注.
|
/// 备注.
|
||||||
|
|||||||
@@ -67,4 +67,9 @@ public class ProductListOutput
|
|||||||
/// 联系人.
|
/// 联系人.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string contactName { get; set; }
|
public string contactName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 子表数据.
|
||||||
|
/// </summary>
|
||||||
|
public List<ProductEntryEntity> productEntryList { get; set; }
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ namespace JNPF.Extend.Entitys.Dto.Customer;
|
|||||||
/// 客户信息.
|
/// 客户信息.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SuppressSniffer]
|
[SuppressSniffer]
|
||||||
public class CustomerListOutput
|
public class ProductCustomerListOutput
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 主键.
|
/// 主键.
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using JNPF.Common.Contracts;
|
using JNPF.Common.Contracts;
|
||||||
|
using JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
|
||||||
namespace JNPF.Extend.Entitys;
|
namespace JNPF.Extend.Entitys;
|
||||||
|
|||||||
@@ -78,4 +78,10 @@ public class DocumentEntity : CLDEntityBase
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(ColumnName = "F_SORTCODE")]
|
[SugarColumn(ColumnName = "F_SORTCODE")]
|
||||||
public long? SortCode { get; set; }
|
public long? SortCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下载地址.
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(ColumnName = "F_UPLOADERURL")]
|
||||||
|
public string? UploaderUrl { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace JNPF.Extend.Entitys.Entity;
|
|||||||
/// 客户信息.
|
/// 客户信息.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarTable("ext_customer", TableDescription = "客户信息")]
|
[SugarTable("ext_customer", TableDescription = "客户信息")]
|
||||||
public class CustomerEntity : CLEntityBase
|
public class ProductCustomerEntity : CLEntityBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 编码.
|
/// 编码.
|
||||||
@@ -159,19 +159,19 @@ public class ProductEntity : EntityBase<string>
|
|||||||
/// 让利金额.
|
/// 让利金额.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(ColumnName = "F_PartPrice")]
|
[SugarColumn(ColumnName = "F_PartPrice")]
|
||||||
public decimal PartPrice { get; set; }
|
public decimal? PartPrice { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 优惠金额.
|
/// 优惠金额.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(ColumnName = "F_ReducedPrice")]
|
[SugarColumn(ColumnName = "F_ReducedPrice")]
|
||||||
public decimal ReducedPrice { get; set; }
|
public decimal? ReducedPrice { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 折后金额.
|
/// 折后金额.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(ColumnName = "F_DiscountPrice")]
|
[SugarColumn(ColumnName = "F_DiscountPrice")]
|
||||||
public decimal DiscountPrice { get; set; }
|
public decimal? DiscountPrice { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 备注.
|
/// 备注.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace JNPF.Extend.Entitys;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarTable("ext_productgoods")]
|
[SugarTable("ext_productgoods")]
|
||||||
[Tenant(ClaimConst.TENANTID)]
|
[Tenant(ClaimConst.TENANTID)]
|
||||||
public class ProductgoodsEntity
|
public class ProductGoodsEntity
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 主键.
|
/// 主键.
|
||||||
|
|||||||
@@ -84,6 +84,12 @@ public class DocumentService : IDynamicApiController, ITransient
|
|||||||
.WhereIF(input.keyword.IsNotEmptyOrNull(), t => t.FullName.Contains(input.keyword))
|
.WhereIF(input.keyword.IsNotEmptyOrNull(), t => t.FullName.Contains(input.keyword))
|
||||||
.OrderBy(x => x.SortCode).OrderBy(x => x.CreatorTime, OrderByType.Desc)
|
.OrderBy(x => x.SortCode).OrderBy(x => x.CreatorTime, OrderByType.Desc)
|
||||||
.OrderByIF(!string.IsNullOrEmpty(input.keyword), t => t.LastModifyTime, OrderByType.Desc).ToListAsync()).Adapt<List<DocumentListOutput>>();
|
.OrderByIF(!string.IsNullOrEmpty(input.keyword), t => t.LastModifyTime, OrderByType.Desc).ToListAsync()).Adapt<List<DocumentListOutput>>();
|
||||||
|
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 };
|
return new { list = data };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,6 +254,7 @@ public class DocumentService : IDynamicApiController, ITransient
|
|||||||
entity.FilePath = Path.Combine(_filePath, input.file.FileName);
|
entity.FilePath = Path.Combine(_filePath, input.file.FileName);
|
||||||
entity.FileSize = input.file.Length.ToString();
|
entity.FileSize = input.file.Length.ToString();
|
||||||
entity.DeleteMark = 0;
|
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();
|
var isOk = await _repository.AsSugarClient().Insertable(entity).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||||
if (isOk < 1)
|
if (isOk < 1)
|
||||||
throw Oops.Oh(ErrorCode.D8001);
|
throw Oops.Oh(ErrorCode.D8001);
|
||||||
@@ -261,11 +268,12 @@ public class DocumentService : IDynamicApiController, ITransient
|
|||||||
[HttpPost("merge")]
|
[HttpPost("merge")]
|
||||||
public async Task<dynamic> merge([FromForm] ChunkModel input)
|
public async Task<dynamic> 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<AppOptions>("JNPF_App", true).SystemPath, "TemporaryFile", input.identifier);
|
//string directoryPath = Path.Combine(App.GetConfig<AppOptions>("JNPF_App", true).SystemPath, "TemporaryFile", input.identifier);
|
||||||
FileHelper.DeleteDirectory(directoryPath);
|
//FileHelper.DeleteDirectory(directoryPath);
|
||||||
throw Oops.Oh(ErrorCode.D8002);
|
//throw Oops.Oh(ErrorCode.D8002);
|
||||||
|
input.fileName = string.Format("{0}-{1}", DateTime.Now.ParseToUnixTime(), input.fileName);
|
||||||
}
|
}
|
||||||
input.isUpdateName = false;
|
input.isUpdateName = false;
|
||||||
input.type = "document";
|
input.type = "document";
|
||||||
@@ -276,10 +284,11 @@ public class DocumentService : IDynamicApiController, ITransient
|
|||||||
entity.Type = 1;
|
entity.Type = 1;
|
||||||
entity.FullName = input.fileName;
|
entity.FullName = input.fileName;
|
||||||
entity.ParentId = input.parentId;
|
entity.ParentId = input.parentId;
|
||||||
entity.FileExtension = Path.GetExtension(input.fileName).Replace(".", string.Empty);
|
entity.FileExtension = input.extension;
|
||||||
entity.FilePath = output.name;
|
entity.FilePath = output.name;
|
||||||
entity.FileSize = input.fileSize;
|
entity.FileSize = input.fileSize;
|
||||||
entity.DeleteMark = 0;
|
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();
|
var isOk = await _repository.AsSugarClient().Insertable(entity).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||||
if (isOk < 1)
|
if (isOk < 1)
|
||||||
throw Oops.Oh(ErrorCode.D8001);
|
throw Oops.Oh(ErrorCode.D8001);
|
||||||
@@ -299,8 +308,7 @@ public class DocumentService : IDynamicApiController, ITransient
|
|||||||
throw Oops.Oh(ErrorCode.D8000);
|
throw Oops.Oh(ErrorCode.D8000);
|
||||||
var fileName = _userManager.UserId + "|" + entity.FilePath + "|document";
|
var fileName = _userManager.UserId + "|" + entity.FilePath + "|document";
|
||||||
_cacheManager.Set(entity.FilePath, string.Empty);
|
_cacheManager.Set(entity.FilePath, string.Empty);
|
||||||
return new
|
return new {
|
||||||
{
|
|
||||||
name = entity.FullName,
|
name = entity.FullName,
|
||||||
url = "/api/File/Download?encryption=" + DESCEncryption.Encrypt(fileName, "JNPF")
|
url = "/api/File/Download?encryption=" + DESCEncryption.Encrypt(fileName, "JNPF")
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ public class EmailService : IDynamicApiController, ITransient
|
|||||||
var mailAccount = mailConfig.Adapt<MailParameterInfo>();
|
var mailAccount = mailConfig.Adapt<MailParameterInfo>();
|
||||||
if (MailUtil.CheckConnected(mailAccount))
|
if (MailUtil.CheckConnected(mailAccount))
|
||||||
{
|
{
|
||||||
new List<EmailReceiveEntity>();
|
new List<EmailReceiveEntity>();
|
||||||
var startTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd") + " 00:00");
|
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 endTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd") + " 23:59");
|
||||||
var receiveCount = await _repository.AsSugarClient().Queryable<EmailReceiveEntity>().CountAsync(x => x.MAccount == mailConfig.Account && SqlFunc.Between(x.CreatorTime, startTime, endTime));
|
var receiveCount = await _repository.AsSugarClient().Queryable<EmailReceiveEntity>().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;
|
var mailFilePath = FileVariable.EmailFilePath;
|
||||||
foreach (MailFileParameterInfo mailFile in attachmentList)
|
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;
|
mailFile.fileName = mailFile.name;
|
||||||
}
|
}
|
||||||
//发送邮件
|
//发送邮件
|
||||||
@@ -342,7 +342,7 @@ public class EmailService : IDynamicApiController, ITransient
|
|||||||
mailModel.Subject = entity.Subject;
|
mailModel.Subject = entity.Subject;
|
||||||
mailModel.BodyText = HttpUtility.HtmlDecode(entity.BodyText);
|
mailModel.BodyText = HttpUtility.HtmlDecode(entity.BodyText);
|
||||||
mailModel.Attachment = attachmentList;
|
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)
|
if (isOk < 1)
|
||||||
throw Oops.Oh(ErrorCode.COM1008);
|
throw Oops.Oh(ErrorCode.COM1008);
|
||||||
}
|
}
|
||||||
@@ -396,10 +396,10 @@ public class EmailService : IDynamicApiController, ITransient
|
|||||||
[HttpPost("Download")]
|
[HttpPost("Download")]
|
||||||
public async Task Download(AnnexModel fileModel)
|
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))
|
if (await _fileManager.ExistsFile(filePath))
|
||||||
{
|
{
|
||||||
_fileManager.DownloadFileByType(filePath, fileModel.FileName);
|
_fileManager.DownloadFileByType(filePath, fileModel.FileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using JNPF.Common.Enums;
|
|||||||
using JNPF.Common.Extension;
|
using JNPF.Common.Extension;
|
||||||
using JNPF.Common.Filter;
|
using JNPF.Common.Filter;
|
||||||
using JNPF.Common.Helper;
|
using JNPF.Common.Helper;
|
||||||
|
using JNPF.Common.Manager;
|
||||||
using JNPF.Common.Models.NPOI;
|
using JNPF.Common.Models.NPOI;
|
||||||
using JNPF.Common.Security;
|
using JNPF.Common.Security;
|
||||||
using JNPF.DataEncryption;
|
using JNPF.DataEncryption;
|
||||||
@@ -34,12 +35,14 @@ public class EmployeeService : IDynamicApiController, ITransient
|
|||||||
private readonly ISqlSugarRepository<EmployeeEntity> _repository;
|
private readonly ISqlSugarRepository<EmployeeEntity> _repository;
|
||||||
private readonly IFileManager _fileManager;
|
private readonly IFileManager _fileManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
|
private readonly ICacheManager _cacheManager;
|
||||||
|
|
||||||
public EmployeeService(ISqlSugarRepository<EmployeeEntity> repository, IFileManager fileManager, IUserManager userManager)
|
public EmployeeService(ISqlSugarRepository<EmployeeEntity> repository, IFileManager fileManager, IUserManager userManager,ICacheManager cacheManager)
|
||||||
{
|
{
|
||||||
_repository = repository;
|
_repository = repository;
|
||||||
_fileManager = fileManager;
|
_fileManager = fileManager;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
|
_cacheManager = cacheManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region GET
|
#region GET
|
||||||
@@ -114,6 +117,7 @@ public class EmployeeService : IDynamicApiController, ITransient
|
|||||||
//得到数据
|
//得到数据
|
||||||
var sr = await _fileManager.GetFileStream(savePath);
|
var sr = await _fileManager.GetFileStream(savePath);
|
||||||
var excelData = ExcelImportHelper.ToDataTable(savePath, sr);
|
var excelData = ExcelImportHelper.ToDataTable(savePath, sr);
|
||||||
|
excelData.Rows.RemoveAt(0);
|
||||||
foreach (var item in excelData.Columns)
|
foreach (var item in excelData.Columns)
|
||||||
{
|
{
|
||||||
excelData.Columns[item.ToString()].ColumnName = GetFiledEncode(item.ToString());
|
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 addPath = Path.Combine(FileVariable.TemporaryFilePath, excelconfig.FileName);
|
||||||
var stream = ExcelExportHelper<EmployeeEntity>.ExportMemoryStream(dataList, excelconfig);
|
var stream = ExcelExportHelper<EmployeeEntity>.ExportMemoryStream(dataList, excelconfig);
|
||||||
await _fileManager.UploadFileByType(stream, FileVariable.TemporaryFilePath, excelconfig.FileName);
|
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") };
|
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 _fileName = DateTime.Now.ToString("yyyyMMdd") + "_" + SnowflakeIdHelper.NextId() + Path.GetExtension(file.FileName);
|
||||||
var stream = file.OpenReadStream();
|
var stream = file.OpenReadStream();
|
||||||
await _fileManager.UploadFileByType(stream, _filePath, _fileName);
|
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) };
|
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);
|
var stream = await _fileManager.GetFileStream(filePath);
|
||||||
await _fileManager.UploadFileByType(stream, FileVariable.TemporaryFilePath, "职员信息.xlsx");
|
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") };
|
return new { name = "职员信息.xlsx", url = "/api/file/Download?encryption=" + DESCEncryption.Encrypt(_userManager.UserId + "|职员信息.xlsx", "JNPF") };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,14 +44,12 @@ public class OrderService : IDynamicApiController, ITransient
|
|||||||
ISqlSugarRepository<OrderEntity> repository,
|
ISqlSugarRepository<OrderEntity> repository,
|
||||||
IUserManager userManager,
|
IUserManager userManager,
|
||||||
IUsersService usersService,
|
IUsersService usersService,
|
||||||
ICacheManager cacheManager,
|
ICacheManager cacheManager)
|
||||||
IFileManager fileManager)
|
|
||||||
{
|
{
|
||||||
_repository = repository;
|
_repository = repository;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_usersService = usersService;
|
_usersService = usersService;
|
||||||
_cacheManager = cacheManager;
|
_cacheManager = cacheManager;
|
||||||
_fileManager = fileManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region GET
|
#region GET
|
||||||
@@ -141,6 +139,7 @@ public class OrderService : IDynamicApiController, ITransient
|
|||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public async Task<dynamic> GetInfo(string id)
|
public async Task<dynamic> GetInfo(string id)
|
||||||
{
|
{
|
||||||
|
if ("0".Equals(id)) return null;
|
||||||
var data = (await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null)).Adapt<OrderInfoOutput>();
|
var data = (await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null)).Adapt<OrderInfoOutput>();
|
||||||
if (data.IsNullOrEmpty()) return null;
|
if (data.IsNullOrEmpty()) return null;
|
||||||
data.collectionPlanList = (await _repository.AsSugarClient().Queryable<OrderReceivableEntity>().Where(x => x.OrderId == id).ToListAsync()).Adapt<List<CollectionPlanModel>>();
|
data.collectionPlanList = (await _repository.AsSugarClient().Queryable<OrderReceivableEntity>().Where(x => x.OrderId == id).ToListAsync()).Adapt<List<CollectionPlanModel>>();
|
||||||
|
|||||||
@@ -30,10 +30,10 @@ public class ProductClassifyService : IDynamicApiController, ITransient
|
|||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
|
|
||||||
public ProductClassifyService(
|
public ProductClassifyService(
|
||||||
ISqlSugarRepository<ProductClassifyEntity> extProductRepository,
|
ISqlSugarRepository<ProductClassifyEntity> repository,
|
||||||
IUserManager userManager)
|
IUserManager userManager)
|
||||||
{
|
{
|
||||||
_repository = extProductRepository;
|
_repository = repository;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
65
extend/Tnb.Extend/ProductCustomerService.cs
Normal file
65
extend/Tnb.Extend/ProductCustomerService.cs
Normal file
@@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 客户信息.
|
||||||
|
/// </summary>
|
||||||
|
[ApiDescriptionSettings(Tag = "Extend", Name = "Customer", Order = 600)]
|
||||||
|
[Route("api/extend/saleOrder/[controller]")]
|
||||||
|
public class ProductCustomerService : IDynamicApiController, ITransient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 服务基础仓储.
|
||||||
|
/// </summary>
|
||||||
|
private readonly ISqlSugarRepository<ProductCustomerEntity> _repository;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户管理.
|
||||||
|
/// </summary>
|
||||||
|
private readonly IUserManager _userManager;
|
||||||
|
|
||||||
|
public ProductCustomerService(
|
||||||
|
ISqlSugarRepository<ProductCustomerEntity> repository,
|
||||||
|
IUserManager userManager)
|
||||||
|
{
|
||||||
|
_repository = repository;
|
||||||
|
_userManager = userManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region GET
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 客户列表.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("")]
|
||||||
|
public async Task<dynamic> 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
|
||||||
|
}
|
||||||
87
extend/Tnb.Extend/ProductGoodsService.cs
Normal file
87
extend/Tnb.Extend/ProductGoodsService.cs
Normal file
@@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 选择产品.
|
||||||
|
/// </summary>
|
||||||
|
[ApiDescriptionSettings(Tag = "Extend", Name = "Goods", Order = 600)]
|
||||||
|
[Route("api/extend/saleOrder/[controller]")]
|
||||||
|
public class ProductGoodsService : IDynamicApiController, ITransient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 服务基础仓储.
|
||||||
|
/// </summary>
|
||||||
|
private readonly ISqlSugarRepository<ProductGoodsEntity> _repository;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户管理.
|
||||||
|
/// </summary>
|
||||||
|
private readonly IUserManager _userManager;
|
||||||
|
|
||||||
|
public ProductGoodsService(
|
||||||
|
ISqlSugarRepository<ProductGoodsEntity> repository,
|
||||||
|
IUserManager userManager)
|
||||||
|
{
|
||||||
|
_repository = repository;
|
||||||
|
_userManager = userManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region GET
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 产品列表.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("")]
|
||||||
|
public async Task<dynamic> 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<ProductGoodsListOutput>.SqlSugarPageResult(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 商品编码.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("Selector")]
|
||||||
|
public async Task<dynamic> 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
|
||||||
|
}
|
||||||
@@ -43,11 +43,11 @@ public class ProductService : IDynamicApiController, ITransient
|
|||||||
/// 初始化一个<see cref="ProductService"/>类型的新实例.
|
/// 初始化一个<see cref="ProductService"/>类型的新实例.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ProductService(
|
public ProductService(
|
||||||
ISqlSugarRepository<ProductEntity> extProductRepository,
|
ISqlSugarRepository<ProductEntity> repository,
|
||||||
IBillRullService billRullService,
|
IBillRullService billRullService,
|
||||||
IUserManager userManager)
|
IUserManager userManager)
|
||||||
{
|
{
|
||||||
_repository = extProductRepository;
|
_repository = repository;
|
||||||
_billRullService = billRullService;
|
_billRullService = billRullService;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,8 @@ public class ProductService : IDynamicApiController, ITransient
|
|||||||
Price = it.Price,
|
Price = it.Price,
|
||||||
Amount = it.Amount,
|
Amount = it.Amount,
|
||||||
Description = it.Description
|
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
|
.ToListAsync(it => new ProductInfoOutput
|
||||||
{
|
{
|
||||||
id = it.Id,
|
id = it.Id,
|
||||||
@@ -100,6 +101,52 @@ public class ProductService : IDynamicApiController, ITransient
|
|||||||
}))?.FirstOrDefault();
|
}))?.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取全订单示例.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">请求参数.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("Goods")]
|
||||||
|
public async Task<dynamic> 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<List<ProductEntryEntity>>()
|
||||||
|
});
|
||||||
|
return PageResult<ProductListOutput>.SqlSugarPageResult(data);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取订单示例列表.
|
/// 获取订单示例列表.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -119,6 +166,7 @@ public class ProductService : IDynamicApiController, ITransient
|
|||||||
.WhereIF(!string.IsNullOrEmpty(input.contactTel), it => it.ContactTel.Contains(input.contactTel))
|
.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.auditState), it => it.AuditState.Equals(input.auditState))
|
||||||
.WhereIF(!string.IsNullOrEmpty(input.closeState), it => it.CloseState.Equals(input.closeState))
|
.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
|
.Select(it => new ProductListOutput
|
||||||
{
|
{
|
||||||
id = it.Id,
|
id = it.Id,
|
||||||
@@ -133,7 +181,7 @@ public class ProductService : IDynamicApiController, ITransient
|
|||||||
closeState = it.CloseState,
|
closeState = it.CloseState,
|
||||||
closeDate = it.CloseDate,
|
closeDate = it.CloseDate,
|
||||||
contactName = it.ContactName
|
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<ProductListOutput>.SqlSugarPageResult(data);
|
return PageResult<ProductListOutput>.SqlSugarPageResult(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,4 +37,5 @@ public class MessageListOutput
|
|||||||
/// 是否已读(0-未读,1-已读).
|
/// 是否已读(0-未读,1-已读).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? isRead { get; set; }
|
public int? isRead { get; set; }
|
||||||
|
public int? flowType { get; set; }
|
||||||
}
|
}
|
||||||
@@ -65,4 +65,6 @@ public class MessageEntity : CLDEntityBase
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(ColumnName = "F_FILES")]
|
[SugarColumn(ColumnName = "F_FILES")]
|
||||||
public string Files { get; set; }
|
public string Files { get; set; }
|
||||||
|
[SugarColumn(ColumnName = "F_FLOWTYPE")]
|
||||||
|
public int? FlowType { get; set; }
|
||||||
}
|
}
|
||||||
@@ -15,5 +15,5 @@ public interface IMessageService
|
|||||||
/// <param name="title"></param>
|
/// <param name="title"></param>
|
||||||
/// <param name="bodyText"></param>
|
/// <param name="bodyText"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task SentMessage(List<string> toUserIds, string title, string bodyText = null, Dictionary<string, object> bodyDic = null);
|
Task SentMessage(List<string> toUserIds, string title, string bodyText = null, Dictionary<string, object> bodyDic = null, int type = 2, string flowType = "1");
|
||||||
}
|
}
|
||||||
@@ -6,5 +6,7 @@ public interface ISendMessageService
|
|||||||
{
|
{
|
||||||
Task<string> SendMessage(MessageSendModel messageSendModel, Dictionary<string, object> bodyDic);
|
Task<string> SendMessage(MessageSendModel messageSendModel, Dictionary<string, object> bodyDic);
|
||||||
|
|
||||||
Task SendMessageDefult(string enCode, List<string> toUser, string taskName, Dictionary<string, object> bodyDic);
|
Task SendMessageDefult(string enCode, List<string> toUser, string creatorUser, string flowName, Dictionary<string, object> bodyDic);
|
||||||
|
Task SendMessageDelegate(string delegateType, string ToUserId, string flowName);
|
||||||
|
Task SendMessageSystem(string enCode);
|
||||||
}
|
}
|
||||||
@@ -95,7 +95,7 @@ public class MessageAccountService : IDynamicApiController, ITransient
|
|||||||
[HttpPost("")]
|
[HttpPost("")]
|
||||||
public async Task Create([FromBody] MessageAccountListOutput input)
|
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);
|
throw Oops.Oh(ErrorCode.COM1004);
|
||||||
var entity = input.Adapt<MessageAccountEntity>();
|
var entity = input.Adapt<MessageAccountEntity>();
|
||||||
var isOk = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
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}")]
|
[HttpPut("{id}")]
|
||||||
public async Task Update(string id, [FromBody] MessageAccountListOutput input)
|
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);
|
throw Oops.Oh(ErrorCode.COM1004);
|
||||||
if ((await _repository.AsSugarClient().Queryable<MessageSendTemplateEntity>().AnyAsync(x => x.AccountConfigId == id && x.DeleteMark == null)) && input.enabledMark == 0)
|
if ((await _repository.AsSugarClient().Queryable<MessageSendTemplateEntity>().AnyAsync(x => x.AccountConfigId == id && x.DeleteMark == null)) && input.enabledMark == 0)
|
||||||
throw Oops.Oh(ErrorCode.D7013);
|
throw Oops.Oh(ErrorCode.D7013);
|
||||||
@@ -153,6 +153,8 @@ public class MessageAccountService : IDynamicApiController, ITransient
|
|||||||
entity.FullName = string.Format("{0}副本{1}", entity.FullName, random);
|
entity.FullName = string.Format("{0}副本{1}", entity.FullName, random);
|
||||||
entity.EnCode = string.Format("{0}{1}", entity.EnCode, random);
|
entity.EnCode = string.Format("{0}{1}", entity.EnCode, random);
|
||||||
entity.EnabledMark = 0;
|
entity.EnabledMark = 0;
|
||||||
|
entity.LastModifyTime = null;
|
||||||
|
entity.LastModifyUserId = null;
|
||||||
if (entity.Type == "7")
|
if (entity.Type == "7")
|
||||||
{
|
{
|
||||||
entity.AppKey = string.Format("{0}{1}", entity.AppKey, random);
|
entity.AppKey = string.Format("{0}{1}", entity.AppKey, random);
|
||||||
|
|||||||
@@ -119,7 +119,8 @@ public class MessageService : IMessageService, IDynamicApiController, ITransient
|
|||||||
releaseUser = SqlFunc.MergeString(c.RealName, "/", c.Account),
|
releaseUser = SqlFunc.MergeString(c.RealName, "/", c.Account),
|
||||||
title = a.Title,
|
title = a.Title,
|
||||||
type = a.Type,
|
type = a.Type,
|
||||||
isRead = b.IsRead
|
isRead = b.IsRead,
|
||||||
|
flowType=a.FlowType
|
||||||
}).ToPagedListAsync(input.currentPage, input.pageSize);
|
}).ToPagedListAsync(input.currentPage, input.pageSize);
|
||||||
return PageResult<MessageListOutput>.SqlSugarPageResult(list);
|
return PageResult<MessageListOutput>.SqlSugarPageResult(list);
|
||||||
}
|
}
|
||||||
@@ -297,7 +298,7 @@ public class MessageService : IMessageService, IDynamicApiController, ITransient
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_repository.AsSugarClient().Insertable(receiveEntityList).ExecuteCommandAsync();
|
_repository.AsSugarClient().Insertable(receiveEntityList).ExecuteCommand();
|
||||||
|
|
||||||
return _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Create()).ExecuteCommand();
|
return _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Create()).ExecuteCommand();
|
||||||
}
|
}
|
||||||
@@ -317,7 +318,7 @@ public class MessageService : IMessageService, IDynamicApiController, ITransient
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_repository.AsSugarClient().Insertable(receiveEntityList).ExecuteCommandAsync();
|
_repository.AsSugarClient().Insertable(receiveEntityList).ExecuteCommand();
|
||||||
return _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommand();
|
return _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommand();
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@@ -405,7 +406,7 @@ public class MessageService : IMessageService, IDynamicApiController, ITransient
|
|||||||
/// <param name="title">标题.</param>
|
/// <param name="title">标题.</param>
|
||||||
/// <param name="bodyText">内容.</param>
|
/// <param name="bodyText">内容.</param>
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public async Task SentMessage(List<string> toUserIds, string title, string bodyText = null, Dictionary<string, object> bodyDic = null)
|
public async Task SentMessage(List<string> toUserIds, string title, string bodyText = null, Dictionary<string, object> bodyDic = null, int type = 2, string flowType = "1")
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -413,9 +414,10 @@ public class MessageService : IMessageService, IDynamicApiController, ITransient
|
|||||||
entity.Id = SnowflakeIdHelper.NextId();
|
entity.Id = SnowflakeIdHelper.NextId();
|
||||||
entity.Title = title;
|
entity.Title = title;
|
||||||
entity.BodyText = bodyText;
|
entity.BodyText = bodyText;
|
||||||
entity.Type = 2;
|
entity.Type = type;
|
||||||
entity.LastModifyTime = DateTime.Now;
|
entity.LastModifyTime = DateTime.Now;
|
||||||
entity.LastModifyUserId = _userManager.UserId;
|
entity.LastModifyUserId = _userManager.UserId;
|
||||||
|
entity.FlowType = flowType.ParseToInt();
|
||||||
List<MessageReceiveEntity> receiveEntityList = toUserIds
|
List<MessageReceiveEntity> receiveEntityList = toUserIds
|
||||||
.Select(x => new MessageReceiveEntity()
|
.Select(x => new MessageReceiveEntity()
|
||||||
{
|
{
|
||||||
@@ -432,7 +434,7 @@ public class MessageService : IMessageService, IDynamicApiController, ITransient
|
|||||||
{
|
{
|
||||||
var userId = item.Replace("-delegate", string.Empty);
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,6 +194,8 @@ public class MessageTemplateService : IDynamicApiController, ITransient
|
|||||||
entity.Id = SnowflakeIdHelper.NextId();
|
entity.Id = SnowflakeIdHelper.NextId();
|
||||||
entity.EnabledMark = 0;
|
entity.EnabledMark = 0;
|
||||||
entity.TemplateType = "0";
|
entity.TemplateType = "0";
|
||||||
|
entity.LastModifyTime = null;
|
||||||
|
entity.LastModifyUserId = null;
|
||||||
if (entity.FullName.Length >= 50 || entity.EnCode.Length >= 50)
|
if (entity.FullName.Length >= 50 || entity.EnCode.Length >= 50)
|
||||||
throw Oops.Oh(ErrorCode.COM1009);
|
throw Oops.Oh(ErrorCode.COM1009);
|
||||||
var templateParamList = await _repository.AsSugarClient().Queryable<MessageTemplateParamEntity>().Where(x => x.TemplateId == id && x.DeleteMark == null).ToListAsync();
|
var templateParamList = await _repository.AsSugarClient().Queryable<MessageTemplateParamEntity>().Where(x => x.TemplateId == id && x.DeleteMark == null).ToListAsync();
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class SendMessageService : ISendMessageService, IDynamicApiController, IT
|
|||||||
{
|
{
|
||||||
fullName = b.FullName,
|
fullName = b.FullName,
|
||||||
type = a.MessageType,
|
type = a.MessageType,
|
||||||
}).ToListAsync();
|
}).Distinct().ToListAsync();
|
||||||
}
|
}
|
||||||
return PageResult<SendMessageListOutput>.SqlSugarPageResult(list);
|
return PageResult<SendMessageListOutput>.SqlSugarPageResult(list);
|
||||||
}
|
}
|
||||||
@@ -115,10 +115,8 @@ public class SendMessageService : ISendMessageService, IDynamicApiController, IT
|
|||||||
public async Task<dynamic> GetSendList([FromQuery] MessageTemplateQuery input)
|
public async Task<dynamic> GetSendList([FromQuery] MessageTemplateQuery input)
|
||||||
{
|
{
|
||||||
var list = await _repository.AsSugarClient().Queryable<MessageSendEntity>()
|
var list = await _repository.AsSugarClient().Queryable<MessageSendEntity>()
|
||||||
.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.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))
|
.WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword))
|
||||||
.OrderBy(a => a.SortCode)
|
.OrderBy(a => a.SortCode)
|
||||||
.OrderBy(a => a.CreatorTime, OrderByType.Desc)
|
.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.FullName = string.Format("{0}副本{1}", entity.FullName, random);
|
||||||
entity.EnCode = string.Format("{0}{1}", entity.EnCode, random);
|
entity.EnCode = string.Format("{0}{1}", entity.EnCode, random);
|
||||||
entity.Id = SnowflakeIdHelper.NextId();
|
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)
|
if (entity.FullName.Length >= 50 || entity.EnCode.Length >= 50)
|
||||||
throw Oops.Oh(ErrorCode.COM1009);
|
throw Oops.Oh(ErrorCode.COM1009);
|
||||||
var sendTemplateList = await _repository.AsSugarClient().Queryable<MessageSendTemplateEntity>().Where(x => x.SendConfigId == id && x.DeleteMark == null).ToListAsync();
|
var sendTemplateList = await _repository.AsSugarClient().Queryable<MessageSendTemplateEntity>().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;
|
return errorList.Any() ? string.Join(",", errorList) : string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SendMessageDefult(string enCode,List<string> toUser, string taskName, Dictionary<string, object> bodyDic)
|
public async Task SendMessageDefult(string enCode, List<string> toUser,string creatorUser, string flowName, Dictionary<string, object> bodyDic)
|
||||||
{
|
{
|
||||||
var msgTemplateEntity= await _repository.AsSugarClient().Queryable<MessageTemplateEntity>().FirstAsync(x => x.EnCode == enCode && x.TemplateType=="1" && x.DeleteMark == null);
|
var msgTemplateEntity= await _repository.AsSugarClient().Queryable<MessageTemplateEntity>().FirstAsync(x => x.EnCode == enCode && x.TemplateType=="1" && x.DeleteMark == null);
|
||||||
msgTemplateEntity.Title= msgTemplateEntity.Title.Replace("@流程发起人@流程名称", taskName);
|
msgTemplateEntity.Title = msgTemplateEntity.Title.Replace("@流程发起人", creatorUser).Replace("@流程名称", flowName);
|
||||||
msgTemplateEntity.Content = msgTemplateEntity.Content.Replace("@流程发起人@流程名称", taskName);
|
msgTemplateEntity.Content = msgTemplateEntity.Content.Replace("@流程发起人", creatorUser).Replace("@流程名称", flowName);
|
||||||
await _messageService.SentMessage(toUser, msgTemplateEntity.Title, msgTemplateEntity.Content, bodyDic);
|
await _messageService.SentMessage(toUser, msgTemplateEntity.Title, msgTemplateEntity.Content, bodyDic);
|
||||||
#region 消息监控
|
#region 消息监控
|
||||||
foreach (var item in toUser)
|
foreach (var item in toUser)
|
||||||
@@ -482,6 +484,21 @@ public class SendMessageService : ISendMessageService, IDynamicApiController, IT
|
|||||||
}
|
}
|
||||||
#endregion
|
#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<string, object>();
|
||||||
|
bodyDic.Add(ToUserId, parameter);
|
||||||
|
await _messageService.SentMessage(new List<string>() { ToUserId }, title, null, bodyDic, 2, "2");
|
||||||
|
}
|
||||||
|
public async Task SendMessageSystem(string enCode)
|
||||||
|
{
|
||||||
|
var msgTemplateEntity = await _repository.AsSugarClient().Queryable<MessageTemplateEntity>().FirstAsync(x => x.EnCode == enCode && x.TemplateType == "1" && x.DeleteMark == null);
|
||||||
|
var bodyDic = new Dictionary<string, object>();
|
||||||
|
bodyDic.Add(_userManager.UserId, msgTemplateEntity.Content);
|
||||||
|
await _messageService.SentMessage(new List<string>() { _userManager.UserId }, msgTemplateEntity.Title, msgTemplateEntity.Content, bodyDic, 3);
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region PrivateMethod
|
#region PrivateMethod
|
||||||
@@ -680,9 +697,13 @@ public class SendMessageService : ISendMessageService, IDynamicApiController, IT
|
|||||||
if (text.IsNotEmptyOrNull())
|
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)
|
foreach (var item in paramDic.Keys)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using JNPF.Common.Security;
|
|||||||
using JNPF.DataEncryption;
|
using JNPF.DataEncryption;
|
||||||
using JNPF.DependencyInjection;
|
using JNPF.DependencyInjection;
|
||||||
using JNPF.DynamicApiController;
|
using JNPF.DynamicApiController;
|
||||||
|
using JNPF.Extras.DatabaseAccessor.SqlSugar.Models;
|
||||||
using JNPF.FriendlyException;
|
using JNPF.FriendlyException;
|
||||||
using JNPF.Logging.Attributes;
|
using JNPF.Logging.Attributes;
|
||||||
using JNPF.Message.Entitys.Entity;
|
using JNPF.Message.Entitys.Entity;
|
||||||
@@ -92,9 +93,15 @@ public class ShortLinkService : IShortLinkService, IDynamicApiController, ITrans
|
|||||||
options = JNPFTenantExtensions.GetLinkToCustom(tenantId, result.data.linkList);
|
options = JNPFTenantExtensions.GetLinkToCustom(tenantId, result.data.linkList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!"default".Equals(tenantId) && _tenant.MultiTenancyType.Equals("COLUMN"))
|
||||||
|
{
|
||||||
|
_sqlSugarClient.QueryFilter.AddTableFilter<ITenantFilter>(it => it.TenantId == tenantId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
_sqlSugarClient.AddConnection(JNPFTenantExtensions.GetConfig(options));
|
_sqlSugarClient.AddConnection(JNPFTenantExtensions.GetConfig(options));
|
||||||
_sqlSugarClient.ChangeDatabase(tenantId);
|
_sqlSugarClient.ChangeDatabase(tenantId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var entity = await _sqlSugarClient.Queryable<MessageShortLinkEntity>().SingleAsync(x => x.ShortLink == shortLink && x.DeleteMark == null);
|
var entity = await _sqlSugarClient.Queryable<MessageShortLinkEntity>().SingleAsync(x => x.ShortLink == shortLink && x.DeleteMark == null);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user