Merge pull request 'main' (#2) from Admin.NET/Admin.NET.Pro:main into main
Reviewed-on: http://101.43.53.74:3000/coolcalf/Admin.NET.Pro/pulls/2
This commit is contained in:
commit
357cfb57d7
@ -59,12 +59,12 @@ public class AppAuthService : IDynamicApiController, ITransient
|
||||
// 判断密码错误次数(缓存30分钟)
|
||||
var keyPasswordErrorTimes = $"{CacheConst.KeyPasswordErrorTimes}{input.Account}";
|
||||
var passwordErrorTimes = _sysCacheService.Get<int>(keyPasswordErrorTimes);
|
||||
var passwdMaxErrorTimes = await _sysConfigService.GetConfigValue<int>(CommonConst.SysPasswordMaxErrorTimes);
|
||||
var passwdMaxErrorTimes = await _sysConfigService.GetConfigValue<int>(ConfigConst.SysPasswordMaxErrorTimes);
|
||||
if (passwordErrorTimes >= passwdMaxErrorTimes)
|
||||
throw Oops.Oh(ErrorCodeEnum.D1027);
|
||||
|
||||
// 是否开启验证码
|
||||
if (await _sysConfigService.GetConfigValue<bool>(CommonConst.SysCaptcha))
|
||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysCaptcha))
|
||||
{
|
||||
// 判断验证码
|
||||
if (!_captcha.Validate(input.CodeId.ToString(), input.Code))
|
||||
|
||||
@ -18,26 +18,27 @@
|
||||
<PackageReference Include="AspectCore.Extensions.Reflection" Version="2.4.0" />
|
||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="8.14.6" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.4.5" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.4.5" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.4.5" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.4.7" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.4.7" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.4.7" />
|
||||
<PackageReference Include="Hardware.Info" Version="100.1.0.1" />
|
||||
<PackageReference Include="IPTools.China" Version="1.6.0" />
|
||||
<PackageReference Include="IPTools.International" Version="1.6.0" />
|
||||
<PackageReference Include="Magicodes.IE.Excel" Version="2.7.5.1" />
|
||||
<PackageReference Include="Magicodes.IE.Pdf" Version="2.7.5.1" />
|
||||
<PackageReference Include="Magicodes.IE.Word" Version="2.7.5.1" />
|
||||
<PackageReference Include="MailKit" Version="4.7.0" />
|
||||
<PackageReference Include="MailKit" Version="4.7.1.1" />
|
||||
<PackageReference Include="NewLife.Redis" Version="5.7.2024.709" />
|
||||
<PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="3.6.0" />
|
||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
||||
<PackageReference Include="RabbitMQ.Client" Version="6.8.1" />
|
||||
<PackageReference Include="SixLabors.ImageSharp.Web" Version="3.1.2" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="3.3.0" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="3.4.0" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="3.6.0" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.162" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.166" />
|
||||
<PackageReference Include="SSH.NET" Version="2024.1.0" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.4.3" />
|
||||
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1045" />
|
||||
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1051" />
|
||||
<PackageReference Include="UAParser" Version="3.1.47" />
|
||||
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
|
||||
</ItemGroup>
|
||||
|
||||
16
Admin.NET/Admin.NET.Core/Attribute/OwnerOrgAttribute.cs
Normal file
16
Admin.NET/Admin.NET.Core/Attribute/OwnerOrgAttribute.cs
Normal file
@ -0,0 +1,16 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 所属机构数据权限
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
|
||||
public class OwnerOrgAttribute : Attribute
|
||||
{
|
||||
}
|
||||
16
Admin.NET/Admin.NET.Core/Attribute/OwnerUserAttribute.cs
Normal file
16
Admin.NET/Admin.NET.Core/Attribute/OwnerUserAttribute.cs
Normal file
@ -0,0 +1,16 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 所属用户数据权限
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
|
||||
public class OwnerUserAttribute : Attribute
|
||||
{
|
||||
}
|
||||
@ -1,45 +1,22 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 枚举拓展主题样式
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field)]
|
||||
public class ThemeAttribute : Attribute
|
||||
{
|
||||
public string Theme { get; private set; }
|
||||
|
||||
public ThemeAttribute(string theme)
|
||||
{
|
||||
this.Theme = theme;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ThemeExtend
|
||||
{
|
||||
/// <summary>
|
||||
/// 扩展方法
|
||||
/// </summary>
|
||||
/// <param name="enumValue"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetTheme(this Enum enumValue)
|
||||
{
|
||||
Type type = enumValue.GetType();
|
||||
FieldInfo field = type.GetField(enumValue.ToString());
|
||||
if (field.IsDefined(typeof(ThemeAttribute), true))
|
||||
{
|
||||
var themeAttribute = (ThemeAttribute)field.GetCustomAttribute(typeof(ThemeAttribute));
|
||||
return themeAttribute.Theme;
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 枚举拓展主题样式
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field)]
|
||||
public class ThemeAttribute : Attribute
|
||||
{
|
||||
public string Theme { get; private set; }
|
||||
|
||||
public ThemeAttribute(string theme)
|
||||
{
|
||||
this.Theme = theme;
|
||||
}
|
||||
}
|
||||
@ -100,4 +100,9 @@ public class CacheConst
|
||||
/// 系统字典缓存
|
||||
/// </summary>
|
||||
public const string KeyDict = "sys_dict:";
|
||||
|
||||
/// <summary>
|
||||
/// Excel临时文件缓存
|
||||
/// </summary>
|
||||
public const string KeyExcelTemp = "sys_excel_temp:";
|
||||
}
|
||||
@ -12,86 +12,11 @@ namespace Admin.NET.Core;
|
||||
[Const("平台配置")]
|
||||
public class CommonConst
|
||||
{
|
||||
/// <summary>
|
||||
/// 演示环境开关
|
||||
/// </summary>
|
||||
public const string SysDemoEnv = "sys_demo";
|
||||
|
||||
/// <summary>
|
||||
/// 默认密码
|
||||
/// </summary>
|
||||
public const string SysPassword = "sys_password";
|
||||
|
||||
/// <summary>
|
||||
/// 密码最大错误次数
|
||||
/// </summary>
|
||||
public const string SysPasswordMaxErrorTimes = "sys_password_max_error_times";
|
||||
|
||||
/// <summary>
|
||||
/// 登录二次验证
|
||||
/// </summary>
|
||||
public const string SysSecondVer = "sys_second_ver";
|
||||
|
||||
/// <summary>
|
||||
/// 开启图形验证码
|
||||
/// </summary>
|
||||
public const string SysCaptcha = "sys_captcha";
|
||||
|
||||
/// <summary>
|
||||
/// 开启水印
|
||||
/// </summary>
|
||||
public const string SysWatermark = "sys_watermark";
|
||||
|
||||
/// <summary>
|
||||
/// 开启操作日志
|
||||
/// </summary>
|
||||
public const string SysOpLog = "sys_oplog";
|
||||
|
||||
/// <summary>
|
||||
/// Token过期时间
|
||||
/// </summary>
|
||||
public const string SysTokenExpire = "sys_token_expire";
|
||||
|
||||
/// <summary>
|
||||
/// RefreshToken过期时间
|
||||
/// </summary>
|
||||
public const string SysRefreshTokenExpire = "sys_refresh_token_expire";
|
||||
|
||||
/// <summary>
|
||||
/// 开启发送异常日志邮件
|
||||
/// </summary>
|
||||
public const string SysErrorMail = "sys_error_mail";
|
||||
|
||||
/// <summary>
|
||||
/// 单用户登录
|
||||
/// </summary>
|
||||
public const string SysSingleLogin = "sys_single_login";
|
||||
|
||||
/// <summary>
|
||||
/// 系统管理员角色编码
|
||||
/// </summary>
|
||||
public const string SysAdminRole = "sys_admin";
|
||||
|
||||
///// <summary>
|
||||
///// 开启全局脱敏处理(默认不开启)
|
||||
///// </summary>
|
||||
//public static bool SysSensitiveDetection = false;
|
||||
|
||||
/// <summary>
|
||||
/// 开启域登录验证
|
||||
/// </summary>
|
||||
public const string SysDomainLogin = "sys_domain_login";
|
||||
|
||||
/// <summary>
|
||||
/// 开启记录数据校验日志
|
||||
/// </summary>
|
||||
public const string SysValidationLog = "sys_validation_log";
|
||||
|
||||
/// <summary>
|
||||
/// 日志保留天数
|
||||
/// </summary>
|
||||
public const string SysLogRetentionDays = "sys_log_retention_days";
|
||||
|
||||
/// <summary>
|
||||
/// 日志分组名称
|
||||
/// </summary>
|
||||
|
||||
128
Admin.NET/Admin.NET.Core/Const/ConfigConst.cs
Normal file
128
Admin.NET/Admin.NET.Core/Const/ConfigConst.cs
Normal file
@ -0,0 +1,128 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 配置常量
|
||||
/// </summary>
|
||||
public class ConfigConst
|
||||
{
|
||||
/// <summary>
|
||||
/// 演示环境
|
||||
/// </summary>
|
||||
public const string SysDemoEnv = "sys_demo";
|
||||
|
||||
/// <summary>
|
||||
/// 默认密码
|
||||
/// </summary>
|
||||
public const string SysPassword = "sys_password";
|
||||
|
||||
/// <summary>
|
||||
/// 密码最大错误次数
|
||||
/// </summary>
|
||||
public const string SysPasswordMaxErrorTimes = "sys_password_max_error_times";
|
||||
|
||||
/// <summary>
|
||||
/// 日志保留天数
|
||||
/// </summary>
|
||||
public const string SysLogRetentionDays = "sys_log_retention_days";
|
||||
|
||||
/// <summary>
|
||||
/// 记录操作日志
|
||||
/// </summary>
|
||||
public const string SysOpLog = "sys_oplog";
|
||||
|
||||
/// <summary>
|
||||
/// 单设备登录
|
||||
/// </summary>
|
||||
public const string SysSingleLogin = "sys_single_login";
|
||||
|
||||
/// <summary>
|
||||
/// 登录二次验证
|
||||
/// </summary>
|
||||
public const string SysSecondVer = "sys_second_ver";
|
||||
|
||||
/// <summary>
|
||||
/// 图形验证码
|
||||
/// </summary>
|
||||
public const string SysCaptcha = "sys_captcha";
|
||||
|
||||
/// <summary>
|
||||
/// Token过期时间
|
||||
/// </summary>
|
||||
public const string SysTokenExpire = "sys_token_expire";
|
||||
|
||||
/// <summary>
|
||||
/// RefreshToken过期时间
|
||||
/// </summary>
|
||||
public const string SysRefreshTokenExpire = "sys_refresh_token_expire";
|
||||
|
||||
/// <summary>
|
||||
/// 发送异常日志邮件
|
||||
/// </summary>
|
||||
public const string SysErrorMail = "sys_error_mail";
|
||||
|
||||
/// <summary>
|
||||
/// 域登录验证
|
||||
/// </summary>
|
||||
public const string SysDomainLogin = "sys_domain_login";
|
||||
|
||||
/// <summary>
|
||||
/// 数据校验日志
|
||||
/// </summary>
|
||||
public const string SysValidationLog = "sys_validation_log";
|
||||
|
||||
/// <summary>
|
||||
/// 行政区域同步层级 1-省级,2-市级,3-区县级,4-街道级,5-村级
|
||||
/// </summary>
|
||||
public const string SysRegionSyncLevel = "sys_region_sync_level";
|
||||
|
||||
/// <summary>
|
||||
/// WebConfig 分组
|
||||
/// </summary>
|
||||
public const string SysWebConfigGroup = "WebConfig";
|
||||
|
||||
/// <summary>
|
||||
/// 系统图标
|
||||
/// </summary>
|
||||
public const string SysWebLogo = "sys_web_logo";
|
||||
|
||||
/// <summary>
|
||||
/// 系统主标题
|
||||
/// </summary>
|
||||
public const string SysWebTitle = "sys_web_title";
|
||||
|
||||
/// <summary>
|
||||
/// 系统副标题
|
||||
/// </summary>
|
||||
public const string SysWebViceTitle = "sys_web_viceTitle";
|
||||
|
||||
/// <summary>
|
||||
/// 系统描述
|
||||
/// </summary>
|
||||
public const string SysWebViceDesc = "sys_web_viceDesc";
|
||||
|
||||
/// <summary>
|
||||
/// 水印内容
|
||||
/// </summary>
|
||||
public const string SysWebWatermark = "sys_web_watermark";
|
||||
|
||||
/// <summary>
|
||||
/// 版权说明
|
||||
/// </summary>
|
||||
public const string SysWebCopyright = "sys_web_copyright";
|
||||
|
||||
/// <summary>
|
||||
/// ICP备案号
|
||||
/// </summary>
|
||||
public const string SysWebIcp = "sys_web_icp";
|
||||
|
||||
/// <summary>
|
||||
/// ICP地址
|
||||
/// </summary>
|
||||
public const string SysWebIcpUrl = "sys_web_icpUrl";
|
||||
}
|
||||
@ -27,19 +27,20 @@ public abstract class EntityBase : EntityBaseId, IDeletedFilter
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "创建时间", IsNullable = true, IsOnlyIgnoreUpdate = true, InsertServerTime = true)]
|
||||
[SugarColumn(ColumnDescription = "创建时间", IsNullable = true, IsOnlyIgnoreUpdate = true)]
|
||||
public virtual DateTime CreateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "更新时间", IsOnlyIgnoreInsert = true, UpdateServerTime = true)]
|
||||
[SugarColumn(ColumnDescription = "更新时间", IsOnlyIgnoreInsert = true)]
|
||||
public virtual DateTime? UpdateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建者Id
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "创建者Id", IsOnlyIgnoreUpdate = true)]
|
||||
[OwnerUser]
|
||||
public virtual long? CreateUserId { get; set; }
|
||||
|
||||
///// <summary>
|
||||
@ -92,6 +93,7 @@ public abstract class EntityBaseData : EntityBase, IOrgIdFilter
|
||||
/// 创建者部门Id
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "创建者部门Id", IsOnlyIgnoreUpdate = true)]
|
||||
[OwnerOrg]
|
||||
public virtual long? CreateOrgId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
52
Admin.NET/Admin.NET.Core/Entity/SysSchedule.cs
Normal file
52
Admin.NET/Admin.NET.Core/Entity/SysSchedule.cs
Normal file
@ -0,0 +1,52 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 系统日程表
|
||||
/// </summary>
|
||||
[SugarTable(null, "系统日程表")]
|
||||
[SysTable]
|
||||
public class SysSchedule : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户Id
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "用户Id")]
|
||||
public long UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 日程日期
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "日程日期")]
|
||||
public DateTime? ScheduleTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 开始时间
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "开始时间", Length = 10)]
|
||||
public string? StartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 结束时间
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "结束时间", Length = 10)]
|
||||
public string? EndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 日程内容
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "日程内容", Length = 256)]
|
||||
[Required, MaxLength(256)]
|
||||
public virtual string Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 完成状态
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "完成状态")]
|
||||
public FinishStatusEnum Status { get; set; } = FinishStatusEnum.UnFinish;
|
||||
}
|
||||
@ -11,7 +11,7 @@ namespace Admin.NET.Core;
|
||||
/// </summary>
|
||||
[SugarTable(null, "系统微信支付表")]
|
||||
[SysTable]
|
||||
[SugarIndex("sys_wechat_pay_order_id", nameof(OrderId), OrderByType.Desc)]
|
||||
[SugarIndex("index_{table}_O", nameof(OrderId), OrderByType.Desc)]
|
||||
public partial class SysWechatPay : EntityBase
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@ -11,7 +11,7 @@ namespace Admin.NET.Core;
|
||||
/// </summary>
|
||||
[SugarTable(null, "系统微信退款表")]
|
||||
[SysTable]
|
||||
[SugarIndex("sys_wechat_refund_order_id", nameof(OrderId), OrderByType.Desc)]
|
||||
[SugarIndex("index_{table}_O", nameof(OrderId), OrderByType.Desc)]
|
||||
public class SysWechatRefund : EntityBase
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@ -211,6 +211,18 @@ public enum ErrorCodeEnum
|
||||
[ErrorCodeItemMetadata("系统默认账号禁止删除")]
|
||||
D1029,
|
||||
|
||||
/// <summary>
|
||||
/// 开放接口绑定账号禁止删除
|
||||
/// </summary>
|
||||
[ErrorCodeItemMetadata("开放接口绑定账号禁止删除")]
|
||||
D1030,
|
||||
|
||||
/// <summary>
|
||||
/// 开放接口绑定租户禁止删除
|
||||
/// </summary>
|
||||
[ErrorCodeItemMetadata("开放接口绑定租户禁止删除")]
|
||||
D1031,
|
||||
|
||||
/// <summary>
|
||||
/// 父机构不存在
|
||||
/// </summary>
|
||||
@ -679,6 +691,24 @@ public enum ErrorCodeEnum
|
||||
[ErrorCodeItemMetadata("已有相同编码或名称")]
|
||||
R2002,
|
||||
|
||||
/// <summary>
|
||||
/// 行政区代码只能为6、9或12位
|
||||
/// </summary>
|
||||
[ErrorCodeItemMetadata("行政区代码只能为6、9或12位")]
|
||||
R2003,
|
||||
|
||||
/// <summary>
|
||||
/// 父节点不能为自己的子节点
|
||||
/// </summary>
|
||||
[ErrorCodeItemMetadata("父节点不能为自己的子节点")]
|
||||
R2004,
|
||||
|
||||
/// <summary>
|
||||
/// 同步国家统计局数据异常,请稍后重试
|
||||
/// </summary>
|
||||
[ErrorCodeItemMetadata("同步国家统计局数据异常,请稍后重试")]
|
||||
R2005,
|
||||
|
||||
/// <summary>
|
||||
/// 默认租户状态禁止修改
|
||||
/// </summary>
|
||||
|
||||
32
Admin.NET/Admin.NET.Core/Enum/FilterLogicEnum.cs
Normal file
32
Admin.NET/Admin.NET.Core/Enum/FilterLogicEnum.cs
Normal file
@ -0,0 +1,32 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 过滤条件
|
||||
/// </summary>
|
||||
[Description("过滤条件")]
|
||||
public enum FilterLogicEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 并且
|
||||
/// </summary>
|
||||
[Description("并且")]
|
||||
And,
|
||||
|
||||
/// <summary>
|
||||
/// 或者
|
||||
/// </summary>
|
||||
[Description("或者")]
|
||||
Or,
|
||||
|
||||
/// <summary>
|
||||
/// 异或
|
||||
/// </summary>
|
||||
[Description("异或")]
|
||||
Xor
|
||||
}
|
||||
68
Admin.NET/Admin.NET.Core/Enum/FilterOperatorEnum.cs
Normal file
68
Admin.NET/Admin.NET.Core/Enum/FilterOperatorEnum.cs
Normal file
@ -0,0 +1,68 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 过滤逻辑运算符
|
||||
/// </summary>
|
||||
[Description("过滤逻辑运算符")]
|
||||
public enum FilterOperatorEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 等于(=)
|
||||
/// </summary>
|
||||
[Description("等于")]
|
||||
EQ,
|
||||
|
||||
/// <summary>
|
||||
/// 不等于(!=)
|
||||
/// </summary>
|
||||
[Description("不等于")]
|
||||
NEQ,
|
||||
|
||||
/// <summary>
|
||||
/// 小于<![CDATA[ < ]]>
|
||||
/// </summary>
|
||||
[Description("小于")]
|
||||
LT,
|
||||
|
||||
/// <summary>
|
||||
/// 小于等于<![CDATA[ <= ]]>
|
||||
/// </summary>
|
||||
[Description("小于等于")]
|
||||
LTE,
|
||||
|
||||
/// <summary>
|
||||
/// 大于(>)
|
||||
/// </summary>
|
||||
[Description("大于")]
|
||||
GT,
|
||||
|
||||
/// <summary>
|
||||
/// 大于等于(>=)
|
||||
/// </summary>
|
||||
[Description("大于等于")]
|
||||
GTE,
|
||||
|
||||
/// <summary>
|
||||
/// 开始包含
|
||||
/// </summary>
|
||||
[Description("开始包含")]
|
||||
StartsWith,
|
||||
|
||||
/// <summary>
|
||||
/// 末尾包含
|
||||
/// </summary>
|
||||
[Description("末尾包含")]
|
||||
EndsWith,
|
||||
|
||||
/// <summary>
|
||||
/// 包含
|
||||
/// </summary>
|
||||
[Description("包含")]
|
||||
Contains
|
||||
}
|
||||
26
Admin.NET/Admin.NET.Core/Enum/FinishStatusEnum.cs
Normal file
26
Admin.NET/Admin.NET.Core/Enum/FinishStatusEnum.cs
Normal file
@ -0,0 +1,26 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 完成状态枚举
|
||||
/// </summary>
|
||||
[Description("完成状态枚举")]
|
||||
public enum FinishStatusEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 已完成
|
||||
/// </summary>
|
||||
[Description("已完成")]
|
||||
Finish = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 未完成
|
||||
/// </summary>
|
||||
[Description("未完成")]
|
||||
UnFinish = 0,
|
||||
}
|
||||
@ -7,26 +7,32 @@
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 性别枚举
|
||||
/// 性别枚举(GB/T 2261.1-2003)
|
||||
/// </summary>
|
||||
[Description("性别枚举")]
|
||||
public enum GenderEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 男
|
||||
/// 未知的性别
|
||||
/// </summary>
|
||||
[Description("男")]
|
||||
[Description("未知的性别")]
|
||||
Unknown = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 男性
|
||||
/// </summary>
|
||||
[Description("男性")]
|
||||
Male = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 女
|
||||
/// 女性
|
||||
/// </summary>
|
||||
[Description("女")]
|
||||
[Description("女性")]
|
||||
Female = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 其他
|
||||
/// 未说明的性别
|
||||
/// </summary>
|
||||
[Description("其他")]
|
||||
Other = 3
|
||||
[Description("未说明的性别")]
|
||||
Unspecified = 9
|
||||
}
|
||||
@ -42,7 +42,8 @@ public class AppEventSubscriber : IEventSubscriber, ISingleton, IDisposable
|
||||
//var mailTemp = File.ReadAllText(mailTempPath);
|
||||
//var mail = await _serviceScope.ServiceProvider.GetRequiredService<IViewEngine>().RunCompileFromCachedAsync(mailTemp, );
|
||||
|
||||
var title = "Admin.NET 系统异常";
|
||||
var webTitle = await _serviceScope.ServiceProvider.GetRequiredService<SysConfigService>().GetConfigValue<string>(ConfigConst.SysWebTitle);
|
||||
var title = $"{webTitle} 系统异常";
|
||||
await _serviceScope.ServiceProvider.GetRequiredService<SysEmailService>().SendEmail(JSON.Serialize(context.Source.Payload), title);
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
using NewLife.Caching.Queues;
|
||||
using Newtonsoft.Json;
|
||||
using System.Threading.Channels;
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
@ -11,6 +13,12 @@ namespace Admin.NET.Core;
|
||||
/// <summary>
|
||||
/// Redis自定义事件源存储器
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 在集群部署时,一般每一个消息只由一个服务节点消费一次。
|
||||
/// 有些特殊情情要通知到服务器群中的每一个节点(比如需要强制加载某些配置、重点服务等),
|
||||
/// 在这种情况下就要以“broadcast:”开头来定义EventId,
|
||||
/// 本系统会把“broadcast:”开头的事件视为“广播消息”保证集群中的每一个服务节点都能消费得到这个消息
|
||||
/// </remarks>
|
||||
public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
@ -23,11 +31,9 @@ public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable
|
||||
/// </summary>
|
||||
private readonly Channel<IEventSource> _channel;
|
||||
|
||||
///// <summary>
|
||||
///// Redis 连接对象
|
||||
///// </summary>
|
||||
//private readonly FullRedis _redis;
|
||||
private IProducerConsumer<ChannelEventSource> _queue;
|
||||
private IProducerConsumer<ChannelEventSource> _queueSingle;
|
||||
|
||||
private RedisStream<string> _queueBroadcast;
|
||||
|
||||
/// <summary>
|
||||
/// 路由键
|
||||
@ -54,24 +60,48 @@ public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable
|
||||
//_redis = redis as FullRedis;
|
||||
_routeKey = routeKey;
|
||||
|
||||
// 创建消息订阅者
|
||||
_queue = cacheProvider.GetQueue<ChannelEventSource>(routeKey);
|
||||
_eventConsumer = new EventConsumer<ChannelEventSource>(_queue);
|
||||
// 创建广播消息订阅者,即所有服务器节点都能收到消息(用来发布重启、Reload配置等消息)
|
||||
FullRedis redis = (FullRedis)cacheProvider.Cache;
|
||||
var clusterOpt = App.GetConfig<ClusterOptions>("Cluster", true);
|
||||
_queueBroadcast = redis.GetStream<string>(routeKey + ":broadcast");
|
||||
_queueBroadcast.Group = clusterOpt.ServerId;//根据服务器标识分配到不同的分组里
|
||||
_queueBroadcast.Expire = TimeSpan.FromSeconds(10);//消息10秒过期()
|
||||
_queueBroadcast.ConsumeAsync(OnConsumeBroadcast);
|
||||
|
||||
// 创建队列消息订阅者,只要有一个服务节点消费了消息即可
|
||||
_queueSingle = redis.GetQueue<ChannelEventSource>(routeKey + ":single");
|
||||
_eventConsumer = new EventConsumer<ChannelEventSource>(_queueSingle);
|
||||
|
||||
// 订阅消息写入 Channel
|
||||
_eventConsumer.Received += (send, cr) =>
|
||||
{
|
||||
// 反序列化消息
|
||||
//var eventSource = JsonConvert.DeserializeObject<ChannelEventSource>(cr);
|
||||
|
||||
// 写入内存管道存储器
|
||||
_channel.Writer.WriteAsync(cr);
|
||||
var oriColor = Console.ForegroundColor;
|
||||
ChannelEventSource ces = (ChannelEventSource)cr;
|
||||
ConsumeChannelEventSource(ces);
|
||||
};
|
||||
|
||||
// 启动消费者
|
||||
_eventConsumer.Start();
|
||||
}
|
||||
|
||||
private Task OnConsumeBroadcast(string source, Message message, CancellationToken token)
|
||||
{
|
||||
ChannelEventSource ces = JsonConvert.DeserializeObject<ChannelEventSource>(source);
|
||||
ConsumeChannelEventSource(ces);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void ConsumeChannelEventSource(ChannelEventSource ces)
|
||||
{
|
||||
// 打印测试事件
|
||||
if (ces.EventId != null && ces.EventId.IndexOf(":Test") > 0)
|
||||
{
|
||||
var oriColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine($"有消息要处理{ces.EventId},{ces.Payload}");
|
||||
Console.ForegroundColor = oriColor;
|
||||
}
|
||||
_channel.Writer.WriteAsync(ces);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将事件源写入存储器
|
||||
/// </summary>
|
||||
@ -82,29 +112,28 @@ public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable
|
||||
{
|
||||
// 空检查
|
||||
if (eventSource == default)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(eventSource));
|
||||
}
|
||||
|
||||
// 这里判断是否是 ChannelEventSource 或者 自定义的 EventSource
|
||||
if (eventSource is ChannelEventSource source)
|
||||
{
|
||||
// 序列化消息
|
||||
//var data = JsonSerializer.Serialize(source);
|
||||
|
||||
//// 获取一个订阅对象
|
||||
//var queue = _redis.GetQueue<ChannelEventSource>(_routeKey);
|
||||
|
||||
// 异步发布
|
||||
await Task.Factory.StartNew(() =>
|
||||
{
|
||||
//queue.Add(source);
|
||||
_queue.Add(source);
|
||||
if (source.EventId != null && source.EventId.StartsWith("broadcast:"))
|
||||
{
|
||||
string str = JsonConvert.SerializeObject(source);
|
||||
_queueBroadcast.Add(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
_queueSingle.Add(source);
|
||||
}
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, System.Threading.Tasks.TaskScheduler.Default);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 这里处理动态订阅问题
|
||||
// 处理动态订阅问题
|
||||
await _channel.Writer.WriteAsync(eventSource, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,242 +1,242 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 枚举拓展
|
||||
/// </summary>
|
||||
public static class EnumExtension
|
||||
{
|
||||
// 枚举显示字典缓存
|
||||
private static readonly ConcurrentDictionary<Type, Dictionary<int, string>> EnumDisplayValueDict = new();
|
||||
|
||||
// 枚举值字典缓存
|
||||
private static readonly ConcurrentDictionary<Type, Dictionary<int, string>> EnumNameValueDict = new();
|
||||
|
||||
// 枚举类型缓存
|
||||
private static ConcurrentDictionary<string, Type> _enumTypeDict;
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举对象Key与名称的字典(缓存)
|
||||
/// </summary>
|
||||
/// <param name="enumType"></param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<int, string> GetEnumDictionary(this Type enumType)
|
||||
{
|
||||
if (!enumType.IsEnum)
|
||||
throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
|
||||
|
||||
// 查询缓存
|
||||
var enumDic = EnumNameValueDict.ContainsKey(enumType) ? EnumNameValueDict[enumType] : new Dictionary<int, string>();
|
||||
if (enumDic.Count != 0)
|
||||
return enumDic;
|
||||
// 取枚举类型的Key/Value字典集合
|
||||
enumDic = GetEnumDictionaryItems(enumType);
|
||||
|
||||
// 缓存
|
||||
EnumNameValueDict[enumType] = enumDic;
|
||||
|
||||
return enumDic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举对象Key与名称的字典
|
||||
/// </summary>
|
||||
/// <param name="enumType"></param>
|
||||
/// <returns></returns>
|
||||
private static Dictionary<int, string> GetEnumDictionaryItems(this Type enumType)
|
||||
{
|
||||
// 获取类型的字段,初始化一个有限长度的字典
|
||||
var enumFields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static);
|
||||
Dictionary<int, string> enumDic = new(enumFields.Length);
|
||||
|
||||
// 遍历字段数组获取key和name
|
||||
foreach (var enumField in enumFields)
|
||||
{
|
||||
var intValue = (int)enumField.GetValue(enumType);
|
||||
enumDic[intValue] = enumField.Name;
|
||||
}
|
||||
|
||||
return enumDic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举类型key与描述的字典(缓存)
|
||||
/// </summary>
|
||||
/// <param name="enumType"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public static Dictionary<int, string> GetEnumDescDictionary(this Type enumType)
|
||||
{
|
||||
if (!enumType.IsEnum)
|
||||
throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
|
||||
|
||||
// 查询缓存
|
||||
var enumDic = EnumDisplayValueDict.ContainsKey(enumType)
|
||||
? EnumDisplayValueDict[enumType]
|
||||
: new Dictionary<int, string>();
|
||||
if (enumDic.Count != 0)
|
||||
return enumDic;
|
||||
// 取枚举类型的Key/Value字典集合
|
||||
enumDic = GetEnumDescDictionaryItems(enumType);
|
||||
|
||||
// 缓存
|
||||
EnumDisplayValueDict[enumType] = enumDic;
|
||||
|
||||
return enumDic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举类型key与描述的字典(没有描述则获取name)
|
||||
/// </summary>
|
||||
/// <param name="enumType"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
private static Dictionary<int, string> GetEnumDescDictionaryItems(this Type enumType)
|
||||
{
|
||||
// 获取类型的字段,初始化一个有限长度的字典
|
||||
var enumFields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static);
|
||||
Dictionary<int, string> enumDic = new(enumFields.Length);
|
||||
|
||||
// 遍历字段数组获取key和name
|
||||
foreach (var enumField in enumFields)
|
||||
{
|
||||
var intValue = (int)enumField.GetValue(enumType);
|
||||
var desc = enumField.GetDescriptionValue<DescriptionAttribute>();
|
||||
enumDic[intValue] = desc != null && !string.IsNullOrEmpty(desc.Description) ? desc.Description : enumField.Name;
|
||||
}
|
||||
|
||||
return enumDic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从程序集中查找指定枚举类型
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <param name="typeName"></param>
|
||||
/// <returns></returns>
|
||||
public static Type TryToGetEnumType(Assembly assembly, string typeName)
|
||||
{
|
||||
// 枚举缓存为空则重新加载枚举类型字典
|
||||
_enumTypeDict ??= LoadEnumTypeDict(assembly);
|
||||
|
||||
// 按名称查找
|
||||
return _enumTypeDict.ContainsKey(typeName) ? _enumTypeDict[typeName] : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从程序集中加载所有枚举类型
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <returns></returns>
|
||||
private static ConcurrentDictionary<string, Type> LoadEnumTypeDict(Assembly assembly)
|
||||
{
|
||||
// 取程序集中所有类型
|
||||
var typeArray = assembly.GetTypes();
|
||||
|
||||
// 过滤非枚举类型,转成字典格式并返回
|
||||
var dict = typeArray.Where(o => o.IsEnum).ToDictionary(o => o.Name, o => o);
|
||||
ConcurrentDictionary<string, Type> enumTypeDict = new(dict);
|
||||
return enumTypeDict;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举的Description
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDescription(this System.Enum value)
|
||||
{
|
||||
return value.GetType().GetMember(value.ToString()).FirstOrDefault()?.GetCustomAttribute<DescriptionAttribute>()
|
||||
?.Description;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举的Description
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDescription(this object value)
|
||||
{
|
||||
return value.GetType().GetMember(value.ToString() ?? string.Empty).FirstOrDefault()
|
||||
?.GetCustomAttribute<DescriptionAttribute>()?.Description;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举的Theme
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetTheme(this object value)
|
||||
{
|
||||
return value.GetType().GetMember(value.ToString() ?? string.Empty).FirstOrDefault()
|
||||
?.GetCustomAttribute<ThemeAttribute>()?.Theme;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将枚举转成枚举信息集合
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static List<EnumEntity> EnumToList(this Type type)
|
||||
{
|
||||
if (!type.IsEnum)
|
||||
throw new ArgumentException("Type '" + type.Name + "' is not an enum.");
|
||||
var arr = System.Enum.GetNames(type);
|
||||
return arr.Select(sl =>
|
||||
{
|
||||
var item = System.Enum.Parse(type, sl);
|
||||
return new EnumEntity
|
||||
{
|
||||
Name = item.ToString(),
|
||||
Describe = item.GetDescription() ?? item.ToString(),
|
||||
Theme = item.GetTheme() ?? string.Empty,
|
||||
Value = item.GetHashCode()
|
||||
};
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 枚举ToList
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static List<T> EnumToList<T>(this Type type)
|
||||
{
|
||||
if (!type.IsEnum)
|
||||
throw new ArgumentException("Type '" + type.Name + "' is not an enum.");
|
||||
var arr = System.Enum.GetNames(type);
|
||||
return arr.Select(name => (T)System.Enum.Parse(type, name)).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 枚举实体
|
||||
/// </summary>
|
||||
public class EnumEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 枚举的描述
|
||||
/// </summary>
|
||||
public string Describe { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 枚举的样式
|
||||
/// </summary>
|
||||
public string Theme { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 枚举名称
|
||||
/// </summary>
|
||||
public string Name { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 枚举对象的值
|
||||
/// </summary>
|
||||
public int Value { set; get; }
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 枚举拓展
|
||||
/// </summary>
|
||||
public static class EnumExtension
|
||||
{
|
||||
// 枚举显示字典缓存
|
||||
private static readonly ConcurrentDictionary<Type, Dictionary<int, string>> EnumDisplayValueDict = new();
|
||||
|
||||
// 枚举值字典缓存
|
||||
private static readonly ConcurrentDictionary<Type, Dictionary<int, string>> EnumNameValueDict = new();
|
||||
|
||||
// 枚举类型缓存
|
||||
private static ConcurrentDictionary<string, Type> _enumTypeDict;
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举对象Key与名称的字典(缓存)
|
||||
/// </summary>
|
||||
/// <param name="enumType"></param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<int, string> GetEnumDictionary(this Type enumType)
|
||||
{
|
||||
if (!enumType.IsEnum)
|
||||
throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
|
||||
|
||||
// 查询缓存
|
||||
var enumDic = EnumNameValueDict.ContainsKey(enumType) ? EnumNameValueDict[enumType] : new Dictionary<int, string>();
|
||||
if (enumDic.Count != 0)
|
||||
return enumDic;
|
||||
// 取枚举类型的Key/Value字典集合
|
||||
enumDic = GetEnumDictionaryItems(enumType);
|
||||
|
||||
// 缓存
|
||||
EnumNameValueDict[enumType] = enumDic;
|
||||
|
||||
return enumDic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举对象Key与名称的字典
|
||||
/// </summary>
|
||||
/// <param name="enumType"></param>
|
||||
/// <returns></returns>
|
||||
private static Dictionary<int, string> GetEnumDictionaryItems(this Type enumType)
|
||||
{
|
||||
// 获取类型的字段,初始化一个有限长度的字典
|
||||
var enumFields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static);
|
||||
Dictionary<int, string> enumDic = new(enumFields.Length);
|
||||
|
||||
// 遍历字段数组获取key和name
|
||||
foreach (var enumField in enumFields)
|
||||
{
|
||||
var intValue = (int)enumField.GetValue(enumType);
|
||||
enumDic[intValue] = enumField.Name;
|
||||
}
|
||||
|
||||
return enumDic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举类型key与描述的字典(缓存)
|
||||
/// </summary>
|
||||
/// <param name="enumType"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public static Dictionary<int, string> GetEnumDescDictionary(this Type enumType)
|
||||
{
|
||||
if (!enumType.IsEnum)
|
||||
throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
|
||||
|
||||
// 查询缓存
|
||||
var enumDic = EnumDisplayValueDict.ContainsKey(enumType)
|
||||
? EnumDisplayValueDict[enumType]
|
||||
: new Dictionary<int, string>();
|
||||
if (enumDic.Count != 0)
|
||||
return enumDic;
|
||||
// 取枚举类型的Key/Value字典集合
|
||||
enumDic = GetEnumDescDictionaryItems(enumType);
|
||||
|
||||
// 缓存
|
||||
EnumDisplayValueDict[enumType] = enumDic;
|
||||
|
||||
return enumDic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举类型key与描述的字典(没有描述则获取name)
|
||||
/// </summary>
|
||||
/// <param name="enumType"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
private static Dictionary<int, string> GetEnumDescDictionaryItems(this Type enumType)
|
||||
{
|
||||
// 获取类型的字段,初始化一个有限长度的字典
|
||||
var enumFields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static);
|
||||
Dictionary<int, string> enumDic = new(enumFields.Length);
|
||||
|
||||
// 遍历字段数组获取key和name
|
||||
foreach (var enumField in enumFields)
|
||||
{
|
||||
var intValue = (int)enumField.GetValue(enumType);
|
||||
var desc = enumField.GetDescriptionValue<DescriptionAttribute>();
|
||||
enumDic[intValue] = desc != null && !string.IsNullOrEmpty(desc.Description) ? desc.Description : enumField.Name;
|
||||
}
|
||||
|
||||
return enumDic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从程序集中查找指定枚举类型
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <param name="typeName"></param>
|
||||
/// <returns></returns>
|
||||
public static Type TryToGetEnumType(Assembly assembly, string typeName)
|
||||
{
|
||||
// 枚举缓存为空则重新加载枚举类型字典
|
||||
_enumTypeDict ??= LoadEnumTypeDict(assembly);
|
||||
|
||||
// 按名称查找
|
||||
return _enumTypeDict.ContainsKey(typeName) ? _enumTypeDict[typeName] : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从程序集中加载所有枚举类型
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <returns></returns>
|
||||
private static ConcurrentDictionary<string, Type> LoadEnumTypeDict(Assembly assembly)
|
||||
{
|
||||
// 取程序集中所有类型
|
||||
var typeArray = assembly.GetTypes();
|
||||
|
||||
// 过滤非枚举类型,转成字典格式并返回
|
||||
var dict = typeArray.Where(o => o.IsEnum).ToDictionary(o => o.Name, o => o);
|
||||
ConcurrentDictionary<string, Type> enumTypeDict = new(dict);
|
||||
return enumTypeDict;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举的Description
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDescription(this System.Enum value)
|
||||
{
|
||||
return value.GetType().GetMember(value.ToString()).FirstOrDefault()?.GetCustomAttribute<DescriptionAttribute>()
|
||||
?.Description;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举的Description
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDescription(this object value)
|
||||
{
|
||||
return value.GetType().GetMember(value.ToString() ?? string.Empty).FirstOrDefault()
|
||||
?.GetCustomAttribute<DescriptionAttribute>()?.Description;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举的Theme
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetTheme(this object value)
|
||||
{
|
||||
return value.GetType().GetMember(value.ToString() ?? string.Empty).FirstOrDefault()
|
||||
?.GetCustomAttribute<ThemeAttribute>()?.Theme;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将枚举转成枚举信息集合
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static List<EnumEntity> EnumToList(this Type type)
|
||||
{
|
||||
if (!type.IsEnum)
|
||||
throw new ArgumentException("Type '" + type.Name + "' is not an enum.");
|
||||
var arr = System.Enum.GetNames(type);
|
||||
return arr.Select(sl =>
|
||||
{
|
||||
var item = System.Enum.Parse(type, sl);
|
||||
return new EnumEntity
|
||||
{
|
||||
Name = item.ToString(),
|
||||
Describe = item.GetDescription() ?? item.ToString(),
|
||||
Theme = item.GetTheme() ?? string.Empty,
|
||||
Value = item.GetHashCode()
|
||||
};
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 枚举ToList
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static List<T> EnumToList<T>(this Type type)
|
||||
{
|
||||
if (!type.IsEnum)
|
||||
throw new ArgumentException("Type '" + type.Name + "' is not an enum.");
|
||||
var arr = System.Enum.GetNames(type);
|
||||
return arr.Select(name => (T)System.Enum.Parse(type, name)).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 枚举实体
|
||||
/// </summary>
|
||||
public class EnumEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 枚举的描述
|
||||
/// </summary>
|
||||
public string Describe { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 枚举的样式
|
||||
/// </summary>
|
||||
public string Theme { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 枚举名称
|
||||
/// </summary>
|
||||
public string Name { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 枚举对象的值
|
||||
/// </summary>
|
||||
public int Value { set; get; }
|
||||
}
|
||||
94
Admin.NET/Admin.NET.Core/Extension/HttpContextExtension.cs
Normal file
94
Admin.NET/Admin.NET.Core/Extension/HttpContextExtension.cs
Normal file
@ -0,0 +1,94 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
public static class HttpContextExtension
|
||||
{
|
||||
public static async Task<AuthenticationScheme[]> GetExternalProvidersAsync(this HttpContext context)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
|
||||
var schemes = context.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
|
||||
return (from scheme in await schemes.GetAllSchemesAsync()
|
||||
where !string.IsNullOrEmpty(scheme.DisplayName)
|
||||
select scheme).ToArray();
|
||||
}
|
||||
|
||||
public static async Task<bool> IsProviderSupportedAsync(this HttpContext context, string provider)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
|
||||
return (from scheme in await context.GetExternalProvidersAsync()
|
||||
where string.Equals(scheme.Name, provider, StringComparison.OrdinalIgnoreCase)
|
||||
select scheme).Any();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取设备信息
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetClientDeviceInfo(this HttpContext context)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
|
||||
return CommonUtil.GetClientDeviceInfo(context.Request.Headers.UserAgent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取浏览器信息
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetClientBrowser(this HttpContext context)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
|
||||
string userAgent = context.Request.Headers.UserAgent;
|
||||
try
|
||||
{
|
||||
if (userAgent != null)
|
||||
{
|
||||
var client = Parser.GetDefault().Parse(userAgent);
|
||||
if (client.Device.IsSpider)
|
||||
return "爬虫";
|
||||
return $"{client.UA.Family} {client.UA.Major}.{client.UA.Minor} / {client.Device.Family}";
|
||||
}
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
return "未知";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取操作系统信息
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetClientOs(this HttpContext context)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
|
||||
string userAgent = context.Request.Headers.UserAgent;
|
||||
try
|
||||
{
|
||||
if (userAgent != null)
|
||||
{
|
||||
var client = Parser.GetDefault().Parse(userAgent);
|
||||
if (client.Device.IsSpider)
|
||||
return "爬虫";
|
||||
return $"{client.OS.Family} {client.OS.Major} {client.OS.Minor}";
|
||||
}
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
return "未知";
|
||||
}
|
||||
}
|
||||
294
Admin.NET/Admin.NET.Core/Extension/SqlSugarExtension.cs
Normal file
294
Admin.NET/Admin.NET.Core/Extension/SqlSugarExtension.cs
Normal file
@ -0,0 +1,294 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Sqlsugar 动态查询扩展方法
|
||||
/// </summary>
|
||||
public static class SqlSugarExtension
|
||||
{
|
||||
public static ISugarQueryable<T> SearchBy<T>(this ISugarQueryable<T> queryable, BaseFilter filter)
|
||||
{
|
||||
return queryable.SearchByKeyword(filter.Keyword)
|
||||
.AdvancedSearch(filter.Search)
|
||||
.AdvancedFilter(filter.Filter);
|
||||
}
|
||||
|
||||
public static ISugarQueryable<T> SearchByKeyword<T>(this ISugarQueryable<T> queryable, string keyword)
|
||||
{
|
||||
return queryable.AdvancedSearch(new Search { Keyword = keyword });
|
||||
}
|
||||
|
||||
public static ISugarQueryable<T> AdvancedSearch<T>(this ISugarQueryable<T> queryable, Search search)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(search?.Keyword))
|
||||
{
|
||||
var paramExpr = Expression.Parameter(typeof(T));
|
||||
|
||||
Expression right = Expression.Constant(false);
|
||||
|
||||
if (search.Fields?.Any() is true)
|
||||
{
|
||||
foreach (string field in search.Fields)
|
||||
{
|
||||
MemberExpression propertyExpr = GetPropertyExpression(field, paramExpr);
|
||||
|
||||
var left = AddSearchPropertyByKeyword<T>(propertyExpr, search.Keyword);
|
||||
|
||||
right = Expression.Or(left, right);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var properties = typeof(T).GetProperties()
|
||||
.Where(prop => Nullable.GetUnderlyingType(prop.PropertyType) == null
|
||||
&& !prop.PropertyType.IsEnum
|
||||
&& Type.GetTypeCode(prop.PropertyType) != TypeCode.Object);
|
||||
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var propertyExpr = Expression.Property(paramExpr, property);
|
||||
|
||||
var left = AddSearchPropertyByKeyword<T>(propertyExpr, search.Keyword);
|
||||
|
||||
right = Expression.Or(left, right);
|
||||
}
|
||||
}
|
||||
|
||||
var lambda = Expression.Lambda<Func<T, bool>>(right, paramExpr);
|
||||
|
||||
return queryable.Where(lambda);
|
||||
}
|
||||
|
||||
return queryable;
|
||||
}
|
||||
|
||||
public static ISugarQueryable<T> AdvancedFilter<T>(this ISugarQueryable<T> queryable, Filter filter)
|
||||
{
|
||||
if (filter is not null)
|
||||
{
|
||||
var parameter = Expression.Parameter(typeof(T));
|
||||
|
||||
Expression binaryExpresioFilter;
|
||||
|
||||
if (filter.Logic.HasValue)
|
||||
{
|
||||
if (filter.Filters is null) throw new ArgumentException("The Filters attribute is required when declaring a logic");
|
||||
binaryExpresioFilter = CreateFilterExpression(filter.Logic.Value, filter.Filters, parameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
var filterValid = GetValidFilter(filter);
|
||||
binaryExpresioFilter = CreateFilterExpression(filterValid.Field!, filterValid.Operator.Value, filterValid.Value, parameter);
|
||||
}
|
||||
|
||||
var lambda = Expression.Lambda<Func<T, bool>>(binaryExpresioFilter, parameter);
|
||||
|
||||
return queryable.Where(lambda);
|
||||
}
|
||||
return queryable;
|
||||
}
|
||||
|
||||
private static Expression CombineFilter(
|
||||
FilterLogicEnum filterLogic,
|
||||
Expression bExpresionBase,
|
||||
Expression bExpresion)
|
||||
{
|
||||
return filterLogic switch
|
||||
{
|
||||
FilterLogicEnum.And => Expression.And(bExpresionBase, bExpresion),
|
||||
FilterLogicEnum.Or => Expression.Or(bExpresionBase, bExpresion),
|
||||
FilterLogicEnum.Xor => Expression.ExclusiveOr(bExpresionBase, bExpresion),
|
||||
_ => throw new ArgumentException("FilterLogic is not valid.", nameof(filterLogic)),
|
||||
};
|
||||
}
|
||||
|
||||
private static Filter GetValidFilter(Filter filter)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filter.Field)) throw new ArgumentException("The field attribute is required when declaring a filter");
|
||||
if (filter.Operator.IsNullOrEmpty()) throw new ArgumentException("The Operator attribute is required when declaring a filter");
|
||||
return filter;
|
||||
}
|
||||
|
||||
private static Expression CreateFilterExpression(
|
||||
FilterLogicEnum filterLogic,
|
||||
IEnumerable<Filter> filters,
|
||||
ParameterExpression parameter)
|
||||
{
|
||||
Expression filterExpression = default!;
|
||||
|
||||
foreach (var filter in filters)
|
||||
{
|
||||
Expression bExpresionFilter;
|
||||
|
||||
if (filter.Logic.HasValue)
|
||||
{
|
||||
if (filter.Filters is null) throw new ArgumentException("The Filters attribute is required when declaring a logic");
|
||||
bExpresionFilter = CreateFilterExpression(filter.Logic.Value, filter.Filters, parameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
var filterValid = GetValidFilter(filter);
|
||||
bExpresionFilter = CreateFilterExpression(filterValid.Field!, filterValid.Operator.Value, filterValid.Value, parameter);
|
||||
}
|
||||
|
||||
filterExpression = filterExpression is null ? bExpresionFilter : CombineFilter(filterLogic, filterExpression, bExpresionFilter);
|
||||
}
|
||||
|
||||
return filterExpression;
|
||||
}
|
||||
|
||||
private static Expression CreateFilterExpression(
|
||||
string field,
|
||||
FilterOperatorEnum filterOperator,
|
||||
object? value,
|
||||
ParameterExpression parameter)
|
||||
{
|
||||
var propertyExpresion = GetPropertyExpression(field, parameter);
|
||||
var valueExpresion = GeValuetExpression(field, value, propertyExpresion.Type);
|
||||
return CreateFilterExpression(propertyExpresion, valueExpresion, filterOperator);
|
||||
}
|
||||
|
||||
private static Expression CreateFilterExpression(
|
||||
MemberExpression memberExpression,
|
||||
ConstantExpression constantExpression,
|
||||
FilterOperatorEnum filterOperator)
|
||||
{
|
||||
return filterOperator switch
|
||||
{
|
||||
FilterOperatorEnum.EQ => Expression.Equal(memberExpression, constantExpression),
|
||||
FilterOperatorEnum.NEQ => Expression.NotEqual(memberExpression, constantExpression),
|
||||
FilterOperatorEnum.LT => Expression.LessThan(memberExpression, constantExpression),
|
||||
FilterOperatorEnum.LTE => Expression.LessThanOrEqual(memberExpression, constantExpression),
|
||||
FilterOperatorEnum.GT => Expression.GreaterThan(memberExpression, constantExpression),
|
||||
FilterOperatorEnum.GTE => Expression.GreaterThanOrEqual(memberExpression, constantExpression),
|
||||
FilterOperatorEnum.Contains => Expression.Call(memberExpression, nameof(FilterOperatorEnum.Contains), null, constantExpression),
|
||||
FilterOperatorEnum.StartsWith => Expression.Call(memberExpression, nameof(FilterOperatorEnum.StartsWith), null, constantExpression),
|
||||
FilterOperatorEnum.EndsWith => Expression.Call(memberExpression, nameof(FilterOperatorEnum.EndsWith), null, constantExpression),
|
||||
_ => throw new ArgumentException("Filter Operator is not valid."),
|
||||
};
|
||||
}
|
||||
|
||||
private static string GetStringFromJsonElement(object value)
|
||||
{
|
||||
if (value is JsonElement) return ((JsonElement)value).GetString()!;
|
||||
if (value is string) return (string)value;
|
||||
return value?.ToString();
|
||||
}
|
||||
|
||||
private static ConstantExpression GeValuetExpression(
|
||||
string field,
|
||||
object? value,
|
||||
Type propertyType)
|
||||
{
|
||||
if (value == null) return Expression.Constant(null, propertyType);
|
||||
|
||||
if (propertyType.IsEnum)
|
||||
{
|
||||
string? stringEnum = GetStringFromJsonElement(value);
|
||||
|
||||
if (!Enum.TryParse(propertyType, stringEnum, true, out object? valueparsed)) throw new ArgumentException(string.Format("Value {0} is not valid for {1}", value, field));
|
||||
|
||||
return Expression.Constant(valueparsed, propertyType);
|
||||
}
|
||||
if (propertyType == typeof(long))
|
||||
{
|
||||
string? stringLong = GetStringFromJsonElement(value);
|
||||
|
||||
if (!long.TryParse(stringLong, out long valueparsed)) throw new ArgumentException(string.Format("Value {0} is not valid for {1}", value, field));
|
||||
|
||||
return Expression.Constant(valueparsed, propertyType);
|
||||
}
|
||||
|
||||
if (propertyType == typeof(Guid))
|
||||
{
|
||||
string? stringGuid = GetStringFromJsonElement(value);
|
||||
|
||||
if (!Guid.TryParse(stringGuid, out Guid valueparsed)) throw new ArgumentException(string.Format("Value {0} is not valid for {1}", value, field));
|
||||
|
||||
return Expression.Constant(valueparsed, propertyType);
|
||||
}
|
||||
|
||||
if (propertyType == typeof(string))
|
||||
{
|
||||
string? text = GetStringFromJsonElement(value);
|
||||
|
||||
return Expression.Constant(text, propertyType);
|
||||
}
|
||||
|
||||
if (propertyType == typeof(DateTime) || propertyType == typeof(DateTime?))
|
||||
{
|
||||
string? text = GetStringFromJsonElement(value);
|
||||
return Expression.Constant(ChangeType(text, propertyType), propertyType);
|
||||
}
|
||||
|
||||
return Expression.Constant(ChangeType(((JsonElement)value).GetRawText(), propertyType), propertyType);
|
||||
}
|
||||
|
||||
private static dynamic? ChangeType(object value, Type conversion)
|
||||
{
|
||||
var t = conversion;
|
||||
|
||||
if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
t = Nullable.GetUnderlyingType(t);
|
||||
}
|
||||
|
||||
return Convert.ChangeType(value, t!);
|
||||
}
|
||||
|
||||
private static MemberExpression GetPropertyExpression(
|
||||
string propertyName,
|
||||
ParameterExpression parameter)
|
||||
{
|
||||
Expression propertyExpression = parameter;
|
||||
foreach (string member in propertyName.Split('.'))
|
||||
{
|
||||
propertyExpression = Expression.PropertyOrField(propertyExpression, member);
|
||||
}
|
||||
|
||||
return (MemberExpression)propertyExpression;
|
||||
}
|
||||
|
||||
private static Expression AddSearchPropertyByKeyword<T>(
|
||||
Expression propertyExpr,
|
||||
string keyword,
|
||||
FilterOperatorEnum operatorSearch = FilterOperatorEnum.Contains)
|
||||
{
|
||||
if (propertyExpr is not MemberExpression memberExpr || memberExpr.Member is not PropertyInfo property)
|
||||
{
|
||||
throw new ArgumentException("propertyExpr must be a property expression.", nameof(propertyExpr));
|
||||
}
|
||||
|
||||
ConstantExpression constant = Expression.Constant(keyword);
|
||||
|
||||
MethodInfo method = operatorSearch switch
|
||||
{
|
||||
FilterOperatorEnum.Contains => typeof(string).GetMethod(nameof(FilterOperatorEnum.Contains), new Type[] { typeof(string) }),
|
||||
FilterOperatorEnum.StartsWith => typeof(string).GetMethod(nameof(FilterOperatorEnum.StartsWith), new Type[] { typeof(string) }),
|
||||
FilterOperatorEnum.EndsWith => typeof(string).GetMethod(nameof(FilterOperatorEnum.EndsWith), new Type[] { typeof(string) }),
|
||||
_ => throw new ArgumentException("Filter Operator is not valid."),
|
||||
};
|
||||
|
||||
Expression selectorExpr =
|
||||
property.PropertyType == typeof(string)
|
||||
? propertyExpr
|
||||
: Expression.Condition(
|
||||
Expression.Equal(Expression.Convert(propertyExpr, typeof(object)), Expression.Constant(null, typeof(object))),
|
||||
Expression.Constant(null, typeof(string)),
|
||||
Expression.Call(propertyExpr, "ToString", null, null));
|
||||
|
||||
return Expression.Call(selectorExpr, method, constant);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
public static class SqlSugarFilterExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据指定Attribute获取属性
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
private static List<string> GetPropertyNames<T>(this Type type)
|
||||
where T : Attribute
|
||||
{
|
||||
var allProperties = type.GetProperties();
|
||||
|
||||
var properties = allProperties.Where(x => x.CustomAttributes.Any(a => a.AttributeType == typeof(T)));
|
||||
|
||||
return properties.Select(x => x.Name).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取过滤表达式
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="owners"></param>
|
||||
/// <returns></returns>
|
||||
public static LambdaExpression GetConditionExpression<T>(this Type type, List<long> owners) where T : Attribute
|
||||
{
|
||||
var fieldNames = type.GetPropertyNames<T>();
|
||||
|
||||
ParameterExpression parameter = Expression.Parameter(type, "c");
|
||||
Expression right = Expression.Constant(false);
|
||||
fieldNames.ForEach(fieldName =>
|
||||
{
|
||||
owners.ForEach(owner =>
|
||||
{
|
||||
var property = type.GetProperty(fieldName);
|
||||
Expression temp = Expression.Property(parameter, property);
|
||||
|
||||
// 如果属性是可为空的类型,则转换为其基础类型
|
||||
var propertyType = property.PropertyType;
|
||||
if (Nullable.GetUnderlyingType(propertyType) != null)
|
||||
{
|
||||
temp = Expression.Convert(temp, Nullable.GetUnderlyingType(propertyType));
|
||||
}
|
||||
|
||||
Expression left = Expression.Equal(temp, Expression.Constant(owner));
|
||||
right = Expression.OrElse(left, right);
|
||||
});
|
||||
});
|
||||
var finalExpression = Expression.Lambda(right, new ParameterExpression[] { parameter });
|
||||
return finalExpression;
|
||||
}
|
||||
}
|
||||
@ -17,6 +17,7 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
|
||||
{
|
||||
private const string GROUP_ONLINE = "GROUP_ONLINE_"; // 租户分组前缀
|
||||
|
||||
private readonly UserManager _userManager;
|
||||
private readonly SqlSugarRepository<SysOnlineUser> _sysOnlineUerRep;
|
||||
private readonly SysMessageService _sysMessageService;
|
||||
private readonly IHubContext<OnlineUserHub, IOnlineUserHub> _onlineUserHubContext;
|
||||
@ -27,13 +28,15 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
|
||||
SysMessageService sysMessageService,
|
||||
IHubContext<OnlineUserHub, IOnlineUserHub> onlineUserHubContext,
|
||||
SysCacheService sysCacheService,
|
||||
SysConfigService sysConfigService)
|
||||
SysConfigService sysConfigService,
|
||||
UserManager userManager)
|
||||
{
|
||||
_sysOnlineUerRep = sysOnlineUerRep;
|
||||
_sysMessageService = sysMessageService;
|
||||
_onlineUserHubContext = onlineUserHubContext;
|
||||
_sysCacheService = sysCacheService;
|
||||
_sysConfigService = sysConfigService;
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -43,34 +46,28 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
|
||||
public override async Task OnConnectedAsync()
|
||||
{
|
||||
var httpContext = Context.GetHttpContext();
|
||||
var token = httpContext.Request.Query["access_token"];
|
||||
var claims = JWTEncryption.ReadJwtToken(token)?.Claims;
|
||||
var client = Parser.GetDefault().Parse(httpContext.Request.Headers["User-Agent"]);
|
||||
|
||||
var userId = claims?.FirstOrDefault(u => u.Type == ClaimConst.UserId)?.Value;
|
||||
var tenantId = claims?.FirstOrDefault(u => u.Type == ClaimConst.TenantId)?.Value;
|
||||
var user = new SysOnlineUser
|
||||
{
|
||||
ConnectionId = Context.ConnectionId,
|
||||
UserId = string.IsNullOrWhiteSpace(userId) ? 0 : long.Parse(userId),
|
||||
UserName = claims?.FirstOrDefault(u => u.Type == ClaimConst.Account)?.Value,
|
||||
RealName = claims?.FirstOrDefault(u => u.Type == ClaimConst.RealName)?.Value,
|
||||
UserId = _userManager.UserId,
|
||||
UserName = _userManager.Account,
|
||||
RealName = _userManager.RealName,
|
||||
Time = DateTime.Now,
|
||||
Ip = httpContext.Connection.RemoteIpAddress.MapToIPv4().ToString(),
|
||||
Browser = client.UA.Family + client.UA.Major,
|
||||
Os = client.OS.Family + client.OS.Major,
|
||||
TenantId = string.IsNullOrWhiteSpace(tenantId) ? 0 : Convert.ToInt64(tenantId),
|
||||
Ip = httpContext.GetRemoteIpAddressToIPv4(true),
|
||||
Browser = httpContext.GetClientBrowser(),
|
||||
Os = httpContext.GetClientOs(),
|
||||
TenantId = _userManager.TenantId,
|
||||
};
|
||||
await _sysOnlineUerRep.InsertAsync(user);
|
||||
|
||||
// 是否开启单用户登录
|
||||
if (await _sysConfigService.GetConfigValue<bool>(CommonConst.SysSingleLogin))
|
||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
||||
{
|
||||
_sysCacheService.Set(CacheConst.KeyUserOnline + user.UserId, user);
|
||||
}
|
||||
else
|
||||
{
|
||||
var device = (client.UA.Family + client.UA.Major + client.OS.Family + client.OS.Major).Trim();
|
||||
var device = httpContext.GetClientDeviceInfo().Trim();
|
||||
_sysCacheService.Set(CacheConst.KeyUserOnline + user.UserId + device, user);
|
||||
}
|
||||
|
||||
@ -98,7 +95,6 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
|
||||
if (string.IsNullOrEmpty(Context.ConnectionId)) return;
|
||||
|
||||
var httpContext = Context.GetHttpContext();
|
||||
var client = Parser.GetDefault().Parse(httpContext.Request.Headers["User-Agent"]);
|
||||
|
||||
var user = await _sysOnlineUerRep.AsQueryable().Filter("", true).FirstAsync(u => u.ConnectionId == Context.ConnectionId);
|
||||
if (user == null) return;
|
||||
@ -106,13 +102,13 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
|
||||
await _sysOnlineUerRep.DeleteAsync(u => u.Id == user.Id);
|
||||
|
||||
// 是否开启单用户登录
|
||||
if (await _sysConfigService.GetConfigValue<bool>(CommonConst.SysSingleLogin))
|
||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
||||
{
|
||||
_sysCacheService.Remove(CacheConst.KeyUserOnline + user.UserId);
|
||||
}
|
||||
else
|
||||
{
|
||||
var device = (client.UA.Family + client.UA.Major + client.OS.Family + client.OS.Major).Trim();
|
||||
var device = httpContext.GetClientDeviceInfo().Trim();
|
||||
_sysCacheService.Remove(CacheConst.KeyUserOnline + user.UserId + device);
|
||||
}
|
||||
|
||||
|
||||
@ -1,149 +1,150 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 枚举转字典
|
||||
/// </summary>
|
||||
[JobDetail("job_EnumToDictJob", Description = "枚举转字典", GroupName = "default", Concurrent = false)]
|
||||
[PeriodSeconds(1, TriggerId = "trigger_EnumToDictJob", Description = "枚举转字典", MaxNumberOfRuns = 1, RunOnStart = true)]
|
||||
public class EnumToDictJob : IJob
|
||||
{
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
private readonly IJsonSerializerProvider _jsonSerializer;
|
||||
|
||||
public EnumToDictJob(IServiceScopeFactory scopeFactory, IJsonSerializerProvider jsonSerializer)
|
||||
{
|
||||
_scopeFactory = scopeFactory;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
}
|
||||
|
||||
public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
|
||||
{
|
||||
using var serviceScope = _scopeFactory.CreateScope();
|
||||
var sysEnumService = serviceScope.ServiceProvider.GetRequiredService<SysEnumService>();
|
||||
var db = serviceScope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
|
||||
|
||||
var enumTypeList = sysEnumService.GetEnumTypeList();
|
||||
var enumCodeList = enumTypeList.Select(u => u.TypeName);
|
||||
var sysDictTypeCodeList = await db.Queryable<SysDictType>().Where(u => enumCodeList.Contains(u.Code)).Select(u => u.Code).ToListAsync(stoppingToken);
|
||||
|
||||
// 更新的枚举转换字典
|
||||
var uEnumType = enumTypeList.Where(u => sysDictTypeCodeList.Contains(u.TypeName)).ToList();
|
||||
var waitUpdateSysDictType = await db.Queryable<SysDictType>().Where(u => uEnumType.Any(a => a.TypeName == u.Code)).ToListAsync(stoppingToken);
|
||||
var waitUpdateSysDictTypeDict = waitUpdateSysDictType.ToDictionary(u => u.Code, u => u);
|
||||
var waitUpdateSysDictData = await db.Queryable<SysDictData>().Where(u => uEnumType.Any(a => a.TypeName == u.DictType.Code)).ToListAsync(stoppingToken);
|
||||
var uSysDictType = new List<SysDictType>();
|
||||
var uSysDictData = new List<SysDictData>();
|
||||
if (uEnumType.Count > 0)
|
||||
{
|
||||
uEnumType.ForEach(e =>
|
||||
{
|
||||
if (waitUpdateSysDictTypeDict.TryGetValue(e.TypeName, out SysDictType value))
|
||||
{
|
||||
var uDictType = value;
|
||||
uDictType.Name = e.TypeDescribe;
|
||||
uDictType.Remark = e.TypeRemark;
|
||||
var uDictData = waitUpdateSysDictData.Where(u => u.DictTypeId == uDictType.Id).ToList();
|
||||
if (uDictData.Count > 0)
|
||||
{
|
||||
uDictData.ForEach(dictData =>
|
||||
{
|
||||
var enumData = e.EnumEntities.Where(u => dictData.Code == u.Name).FirstOrDefault();
|
||||
if (enumData != null)
|
||||
{
|
||||
dictData.Value = enumData.Value.ToString();
|
||||
dictData.Code = enumData.Name;
|
||||
dictData.OrderNo = enumData.Value + 10;
|
||||
dictData.Name = enumData.Describe;
|
||||
uSysDictData.Add(dictData);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!uSysDictType.Any(u => u.Id == uDictType.Id))
|
||||
uSysDictType.Add(uDictType);
|
||||
}
|
||||
});
|
||||
try
|
||||
{
|
||||
db.Ado.BeginTran();
|
||||
|
||||
if (uSysDictType.Count > 0)
|
||||
await db.Updateable(uSysDictType).ExecuteCommandAsync(stoppingToken);
|
||||
|
||||
if (uSysDictData.Count > 0)
|
||||
await db.Updateable(uSysDictData).ExecuteCommandAsync(stoppingToken);
|
||||
|
||||
db.Ado.CommitTran();
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
db.Ado.RollbackTran();
|
||||
Log.Error($"{context.Trigger.Description}更新枚举转换字典入库错误:" + _jsonSerializer.Serialize(error));
|
||||
throw new Exception($"{context.Trigger.Description}更新枚举转换字典入库错误");
|
||||
}
|
||||
}
|
||||
|
||||
// 新增的枚举转换字典
|
||||
var iEnumType = enumTypeList.Where(u => !sysDictTypeCodeList.Contains(u.TypeName)).ToList();
|
||||
if (iEnumType.Count > 0)
|
||||
{
|
||||
// 新增字典类型
|
||||
var iDictType = iEnumType.Select(u => new SysDictType
|
||||
{
|
||||
Id = YitIdHelper.NextId(),
|
||||
Code = u.TypeName,
|
||||
Name = u.TypeDescribe,
|
||||
Remark = u.TypeRemark,
|
||||
Status = StatusEnum.Enable
|
||||
}).ToList();
|
||||
// 新增字典数据
|
||||
var dictData = iEnumType.Join(iDictType, t1 => t1.TypeName, t2 => t2.Code, (t1, t2) => new
|
||||
{
|
||||
data = t1.EnumEntities.Select(u => new SysDictData
|
||||
{
|
||||
Id = YitIdHelper.NextId(), // 性能优化,使用BulkCopyAsync必须手动获取Id
|
||||
DictTypeId = t2.Id,
|
||||
Name = u.Describe,
|
||||
Value = u.Value.ToString(),
|
||||
Code = u.Name,
|
||||
Remark = t2.Remark,
|
||||
OrderNo = u.Value + 10,
|
||||
TagType = "info"
|
||||
}).ToList()
|
||||
}).ToList();
|
||||
var iDictData = new List<SysDictData>();
|
||||
dictData.ForEach(item =>
|
||||
{
|
||||
iDictData.AddRange(item.data);
|
||||
});
|
||||
try
|
||||
{
|
||||
db.Ado.BeginTran();
|
||||
|
||||
if (iDictType.Count > 0)
|
||||
await db.Insertable(iDictType).ExecuteCommandAsync(stoppingToken);
|
||||
|
||||
if (iDictData.Count > 0)
|
||||
await db.Insertable(iDictData).ExecuteCommandAsync(stoppingToken);
|
||||
|
||||
db.Ado.CommitTran();
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
db.Ado.RollbackTran();
|
||||
Log.Error($"{context.Trigger.Description}新增枚举转换字典入库错误:" + _jsonSerializer.Serialize(error));
|
||||
throw new Exception($"{context.Trigger.Description}新增枚举转换字典入库错误");
|
||||
}
|
||||
}
|
||||
|
||||
var originColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine($"【{DateTime.Now}】系统枚举转换字典");
|
||||
Console.ForegroundColor = originColor;
|
||||
}
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 枚举转字典
|
||||
/// </summary>
|
||||
[JobDetail("job_EnumToDictJob", Description = "枚举转字典", GroupName = "default", Concurrent = false)]
|
||||
[PeriodSeconds(1, TriggerId = "trigger_EnumToDictJob", Description = "枚举转字典", MaxNumberOfRuns = 1, RunOnStart = true)]
|
||||
public class EnumToDictJob : IJob
|
||||
{
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
private readonly IJsonSerializerProvider _jsonSerializer;
|
||||
|
||||
public EnumToDictJob(IServiceScopeFactory scopeFactory, IJsonSerializerProvider jsonSerializer)
|
||||
{
|
||||
_scopeFactory = scopeFactory;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
}
|
||||
|
||||
public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
|
||||
{
|
||||
using var serviceScope = _scopeFactory.CreateScope();
|
||||
var sysEnumService = serviceScope.ServiceProvider.GetRequiredService<SysEnumService>();
|
||||
var db = serviceScope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
|
||||
|
||||
var enumTypeList = sysEnumService.GetEnumTypeList();
|
||||
var enumCodeList = enumTypeList.Select(u => u.TypeName);
|
||||
var sysDictTypeCodeList = await db.Queryable<SysDictType>().Where(u => enumCodeList.Contains(u.Code)).Select(u => u.Code).ToListAsync(stoppingToken);
|
||||
|
||||
// 更新的枚举转换字典
|
||||
var uEnumType = enumTypeList.Where(u => sysDictTypeCodeList.Contains(u.TypeName)).ToList();
|
||||
var waitUpdateSysDictType = await db.Queryable<SysDictType>().Where(u => uEnumType.Any(a => a.TypeName == u.Code)).ToListAsync(stoppingToken);
|
||||
var waitUpdateSysDictTypeDict = waitUpdateSysDictType.ToDictionary(u => u.Code, u => u);
|
||||
var waitUpdateSysDictData = await db.Queryable<SysDictData>().Where(u => uEnumType.Any(a => a.TypeName == u.DictType.Code)).ToListAsync(stoppingToken);
|
||||
var uSysDictType = new List<SysDictType>();
|
||||
var uSysDictData = new List<SysDictData>();
|
||||
if (uEnumType.Count > 0)
|
||||
{
|
||||
uEnumType.ForEach(e =>
|
||||
{
|
||||
if (waitUpdateSysDictTypeDict.TryGetValue(e.TypeName, out SysDictType value))
|
||||
{
|
||||
var uDictType = value;
|
||||
uDictType.Name = e.TypeDescribe;
|
||||
uDictType.Remark = e.TypeRemark;
|
||||
var uDictData = waitUpdateSysDictData.Where(u => u.DictTypeId == uDictType.Id).ToList();
|
||||
if (uDictData.Count > 0)
|
||||
{
|
||||
uDictData.ForEach(dictData =>
|
||||
{
|
||||
var enumData = e.EnumEntities.Where(u => dictData.Code == u.Name).FirstOrDefault();
|
||||
if (enumData != null)
|
||||
{
|
||||
dictData.Value = enumData.Value.ToString();
|
||||
dictData.Code = enumData.Name;
|
||||
dictData.OrderNo = enumData.Value + 10;
|
||||
dictData.Name = enumData.Describe;
|
||||
dictData.TagType = enumData.Theme != "" ? enumData.Theme : "info";
|
||||
uSysDictData.Add(dictData);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!uSysDictType.Any(u => u.Id == uDictType.Id))
|
||||
uSysDictType.Add(uDictType);
|
||||
}
|
||||
});
|
||||
try
|
||||
{
|
||||
db.BeginTran();
|
||||
|
||||
if (uSysDictType.Count > 0)
|
||||
await db.Updateable(uSysDictType).ExecuteCommandAsync(stoppingToken);
|
||||
|
||||
if (uSysDictData.Count > 0)
|
||||
await db.Updateable(uSysDictData).ExecuteCommandAsync(stoppingToken);
|
||||
|
||||
db.CommitTran();
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
db.RollbackTran();
|
||||
Log.Error($"{context.Trigger.Description}更新枚举转换字典入库错误:" + _jsonSerializer.Serialize(error));
|
||||
throw new Exception($"{context.Trigger.Description}更新枚举转换字典入库错误");
|
||||
}
|
||||
}
|
||||
|
||||
// 新增的枚举转换字典
|
||||
var iEnumType = enumTypeList.Where(u => !sysDictTypeCodeList.Contains(u.TypeName)).ToList();
|
||||
if (iEnumType.Count > 0)
|
||||
{
|
||||
// 新增字典类型
|
||||
var iDictType = iEnumType.Select(u => new SysDictType
|
||||
{
|
||||
Id = YitIdHelper.NextId(),
|
||||
Code = u.TypeName,
|
||||
Name = u.TypeDescribe,
|
||||
Remark = u.TypeRemark,
|
||||
Status = StatusEnum.Enable
|
||||
}).ToList();
|
||||
// 新增字典数据
|
||||
var dictData = iEnumType.Join(iDictType, t1 => t1.TypeName, t2 => t2.Code, (t1, t2) => new
|
||||
{
|
||||
data = t1.EnumEntities.Select(u => new SysDictData
|
||||
{
|
||||
Id = YitIdHelper.NextId(), // 性能优化,使用BulkCopyAsync必须手动获取Id
|
||||
DictTypeId = t2.Id,
|
||||
Name = u.Describe,
|
||||
Value = u.Value.ToString(),
|
||||
Code = u.Name,
|
||||
Remark = t2.Remark,
|
||||
OrderNo = u.Value + 10,
|
||||
TagType = u.Theme != "" ? u.Theme : "info"
|
||||
}).ToList()
|
||||
}).ToList();
|
||||
var iDictData = new List<SysDictData>();
|
||||
dictData.ForEach(item =>
|
||||
{
|
||||
iDictData.AddRange(item.data);
|
||||
});
|
||||
try
|
||||
{
|
||||
db.BeginTran();
|
||||
|
||||
if (iDictType.Count > 0)
|
||||
await db.Insertable(iDictType).ExecuteCommandAsync(stoppingToken);
|
||||
|
||||
if (iDictData.Count > 0)
|
||||
await db.Insertable(iDictData).ExecuteCommandAsync(stoppingToken);
|
||||
|
||||
db.CommitTran();
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
db.RollbackTran();
|
||||
Log.Error($"{context.Trigger.Description}新增枚举转换字典入库错误:" + _jsonSerializer.Serialize(error));
|
||||
throw new Exception($"{context.Trigger.Description}新增枚举转换字典入库错误");
|
||||
}
|
||||
}
|
||||
|
||||
var originColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine($"【{DateTime.Now}】系统枚举转换字典");
|
||||
Console.ForegroundColor = originColor;
|
||||
}
|
||||
}
|
||||
@ -31,17 +31,18 @@ public class LogJob : IJob
|
||||
var logDiffRep = serviceScope.ServiceProvider.GetRequiredService<SqlSugarRepository<SysLogDiff>>();
|
||||
var sysConfigService = serviceScope.ServiceProvider.GetRequiredService<SysConfigService>();
|
||||
|
||||
var daysAgo = await sysConfigService.GetConfigValue<int>(CommonConst.SysLogRetentionDays); // 日志保留天数
|
||||
await logVisRep.CopyNew().AsDeleteable().Where(u => (DateTime)u.CreateTime < DateTime.Now.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除访问日志
|
||||
await logOpRep.CopyNew().AsDeleteable().Where(u => (DateTime)u.CreateTime < DateTime.Now.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除操作日志
|
||||
await logDiffRep.CopyNew().AsDeleteable().Where(u => (DateTime)u.CreateTime < DateTime.Now.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除差异日志
|
||||
var daysAgo = await sysConfigService.GetConfigValue<int>(ConfigConst.SysLogRetentionDays); // 日志保留天数
|
||||
await logVisRep.CopyNew().AsDeleteable().Where(u => u.CreateTime < DateTime.Now.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除访问日志
|
||||
await logOpRep.CopyNew().AsDeleteable().Where(u => u.CreateTime < DateTime.Now.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除操作日志
|
||||
await logDiffRep.CopyNew().AsDeleteable().Where(u => u.CreateTime < DateTime.Now.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除差异日志
|
||||
|
||||
string msg = $"【{DateTime.Now}】清理系统日志成功,删除 {daysAgo} 天前的日志数据!";
|
||||
var originColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Console.WriteLine($"【{DateTime.Now}】清理系统日志({daysAgo}天前)");
|
||||
Console.WriteLine(msg);
|
||||
Console.ForegroundColor = originColor;
|
||||
|
||||
// 自定义日志
|
||||
_logger.LogInformation($"【{DateTime.Now}】清理系统日志...");
|
||||
_logger.LogInformation(msg);
|
||||
}
|
||||
}
|
||||
@ -31,15 +31,16 @@ public class OnlineUserJob : IJob
|
||||
var rep = serviceScope.ServiceProvider.GetRequiredService<SqlSugarRepository<SysOnlineUser>>();
|
||||
await rep.CopyNew().AsDeleteable().ExecuteCommandAsync(stoppingToken);
|
||||
|
||||
var originColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine($"【{DateTime.Now}】清空在线用户列表");
|
||||
Console.ForegroundColor = originColor;
|
||||
|
||||
// 缓存租户列表
|
||||
await serviceScope.ServiceProvider.GetRequiredService<SysTenantService>().CacheTenant();
|
||||
|
||||
string msg = $"【{DateTime.Now}】清理在线用户成功!服务已重启...";
|
||||
var originColor = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine(msg);
|
||||
Console.ForegroundColor = originColor;
|
||||
|
||||
// 自定义日志
|
||||
_logger.LogInformation($"【{DateTime.Now}】服务已重启...");
|
||||
_logger.LogInformation(msg);
|
||||
}
|
||||
}
|
||||
@ -51,7 +51,7 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
|
||||
|
||||
var loggingMonitor = JSON.Deserialize<dynamic>(jsonStr);
|
||||
// 记录数据校验日志
|
||||
if (loggingMonitor.validation != null && !await _sysConfigService.GetConfigValue<bool>(CommonConst.SysValidationLog)) return;
|
||||
if (loggingMonitor.validation != null && !await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysValidationLog)) return;
|
||||
|
||||
// 获取当前操作者
|
||||
string account = "", realName = "", userId = "", tenantId = "";
|
||||
@ -125,7 +125,7 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
|
||||
}).ExecuteCommandAsync();
|
||||
|
||||
// 将异常日志发送到邮件
|
||||
if (await _sysConfigService.GetConfigValue<bool>(CommonConst.SysErrorMail))
|
||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysErrorMail))
|
||||
{
|
||||
await App.GetRequiredService<IEventPublisher>().PublishAsync(CommonConst.SendErrorMail, logMsg.Exception ?? loggingMonitor.exception);
|
||||
}
|
||||
@ -160,7 +160,7 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
|
||||
}
|
||||
|
||||
// 记录操作日志
|
||||
if (!await _sysConfigService.GetConfigValue<bool>(CommonConst.SysOpLog)) return;
|
||||
if (!await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysOpLog)) return;
|
||||
await _db.Insertable(new SysLogOp
|
||||
{
|
||||
ControllerName = loggingMonitor.controllerName,
|
||||
|
||||
@ -27,7 +27,7 @@ public class ElasticSearchLoggingWriter : IDatabaseLoggingWriter, IDisposable
|
||||
public async Task WriteAsync(LogMessage logMsg, bool flush)
|
||||
{
|
||||
// 是否启用操作日志
|
||||
var sysOpLogEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysOpLog);
|
||||
var sysOpLogEnabled = await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysOpLog);
|
||||
if (!sysOpLogEnabled) return;
|
||||
|
||||
var jsonStr = logMsg.Context?.Get("loggingMonitor")?.ToString();
|
||||
|
||||
@ -19,27 +19,28 @@ public class SysConfigSeedData : ISqlSugarEntitySeedData<SysConfig>
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
new SysConfig{ Id=1300000000101, Name="演示环境", Code="sys_demo", Value="False", SysFlag=YesNoEnum.Y, Remark="演示环境", OrderNo=10, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000111, Name="默认密码", Code="sys_password", Value="123456", SysFlag=YesNoEnum.Y, Remark="默认密码", OrderNo=20, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000121, Name="密码最大错误次数", Code="sys_password_max_error_times", Value="5", SysFlag=YesNoEnum.Y, Remark="允许密码最大输入错误次数", OrderNo=30, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000131, Name="日志保留天数", Code="sys_log_retention_days", Value="180", SysFlag=YesNoEnum.Y, Remark="日志保留天数(天)", OrderNo=40, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000141, Name="记录操作日志", Code="sys_oplog", Value="True", SysFlag=YesNoEnum.Y, Remark="是否记录操作日志", OrderNo=50, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000151, Name="开启单设备登录", Code="sys_single_login", Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启单设备登录", OrderNo=60, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000161, Name="开启登录二次验证", Code="sys_second_ver", Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启登录二次验证", OrderNo=70, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000171, Name="开启图形验证码", Code="sys_captcha", Value="True", SysFlag=YesNoEnum.Y, Remark="是否开启图形验证码", OrderNo=80, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000181, Name="Token过期时间", Code="sys_token_expire", Value="10080", SysFlag=YesNoEnum.Y, Remark="Token过期时间(分钟)", OrderNo=90, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000191, Name="刷新Token过期时间", Code="sys_refresh_token_expire", Value="20160", SysFlag=YesNoEnum.Y, Remark="刷新Token过期时间(分钟)(一般 refresh_token 的有效时间 > 2 * access_token 的有效时间)", OrderNo=100, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000201, Name="发送异常日志邮件", Code="sys_error_mail", Value="True", SysFlag=YesNoEnum.Y, Remark="是否发送异常日志邮件", OrderNo=110, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000211, Name="开启域登录验证", Code="sys_domain_login", Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启域登录验证", OrderNo=120, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000221, Name="开启数据校验日志", Code="sys_validation_log", Value="True", SysFlag=YesNoEnum.Y, Remark="是否数据校验日志", OrderNo=130, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000301, Name="系统主标题", Code="sys_web_title", Value="Admin.NET.Pro", SysFlag=YesNoEnum.Y, Remark="系统主标题", OrderNo=300, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000311, Name="系统副标题", Code="sys_web_viceTitle", Value="Admin.NET.Pro", SysFlag=YesNoEnum.Y, Remark="系统副标题", OrderNo=310, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000321, Name="系统描述", Code="sys_web_viceDesc", Value="站在巨人肩膀上的 .NET 通用权限开发框架", SysFlag=YesNoEnum.Y, Remark="系统描述", OrderNo=320, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000331, Name="水印内容", Code="sys_web_watermark", Value="Admin.NET.Pro", SysFlag=YesNoEnum.Y, Remark="水印内容", OrderNo=330, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000341, Name="版权说明", Code="sys_web_copyright", Value="Copyright © 2021-present Admin.NET All rights reserved.", SysFlag=YesNoEnum.Y, Remark="版权说明", OrderNo=340, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000351, Name="系统图标", Code="sys_web_logo", Value="/Upload/logo.png", SysFlag=YesNoEnum.Y, Remark="系统图标", OrderNo=350, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000361, Name="ICP备案号", Code="sys_web_icp", Value="省ICP备12345678号", SysFlag=YesNoEnum.Y, Remark="ICP备案号", OrderNo=360, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000371, Name="ICP地址", Code="sys_web_icpUrl", Value="https://beian.miit.gov.cn", SysFlag=YesNoEnum.Y, Remark="ICP地址", OrderNo=370, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000101, Name="演示环境", Code=ConfigConst.SysDemoEnv, Value="False", SysFlag=YesNoEnum.Y, Remark="演示环境", OrderNo=10, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000111, Name="默认密码", Code=ConfigConst.SysPassword, Value="123456", SysFlag=YesNoEnum.Y, Remark="默认密码", OrderNo=20, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000121, Name="密码最大错误次数", Code=ConfigConst.SysPasswordMaxErrorTimes, Value="5", SysFlag=YesNoEnum.Y, Remark="允许密码最大输入错误次数", OrderNo=30, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000131, Name="日志保留天数", Code=ConfigConst.SysLogRetentionDays, Value="180", SysFlag=YesNoEnum.Y, Remark="日志保留天数(天)", OrderNo=40, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000141, Name="记录操作日志", Code=ConfigConst.SysOpLog, Value="True", SysFlag=YesNoEnum.Y, Remark="是否记录操作日志", OrderNo=50, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000151, Name="单设备登录", Code=ConfigConst.SysSingleLogin, Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启单设备登录", OrderNo=60, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000161, Name="登录二次验证", Code=ConfigConst.SysSecondVer, Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启登录二次验证", OrderNo=70, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000171, Name="图形验证码", Code=ConfigConst.SysCaptcha, Value="True", SysFlag=YesNoEnum.Y, Remark="是否开启图形验证码", OrderNo=80, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000181, Name="Token过期时间", Code=ConfigConst.SysTokenExpire, Value="10080", SysFlag=YesNoEnum.Y, Remark="Token过期时间(分钟)", OrderNo=90, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000191, Name="RefreshToken过期时间", Code=ConfigConst.SysRefreshTokenExpire, Value="20160", SysFlag=YesNoEnum.Y, Remark="刷新Token过期时间(分钟)(一般 refresh_token 的有效时间 > 2 * access_token 的有效时间)", OrderNo=100, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000201, Name="发送异常日志邮件", Code=ConfigConst.SysErrorMail, Value="True", SysFlag=YesNoEnum.Y, Remark="是否发送异常日志邮件", OrderNo=110, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000211, Name="域登录验证", Code=ConfigConst.SysDomainLogin, Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启域登录验证", OrderNo=120, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000221, Name="数据校验日志", Code=ConfigConst.SysValidationLog, Value="True", SysFlag=YesNoEnum.Y, Remark="是否数据校验日志", OrderNo=130, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000231, Name="行政区域同步层级", Code=ConfigConst.SysRegionSyncLevel, Value="3", SysFlag=YesNoEnum.Y, Remark="行政区域同步层级 1-省级,2-市级,3-区县级,4-街道级,5-村级", OrderNo=140, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000301, Name="系统主标题", Code=ConfigConst.SysWebTitle, Value="Admin.NET.Pro", SysFlag=YesNoEnum.Y, Remark="系统主标题", OrderNo=300, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000311, Name="系统副标题", Code=ConfigConst.SysWebViceTitle, Value="Admin.NET.Pro", SysFlag=YesNoEnum.Y, Remark="系统副标题", OrderNo=310, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000321, Name="系统描述", Code=ConfigConst.SysWebViceDesc, Value="站在巨人肩膀上的 .NET 通用权限开发框架", SysFlag=YesNoEnum.Y, Remark="系统描述", OrderNo=320, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000331, Name="水印内容", Code=ConfigConst.SysWebWatermark, Value="Admin.NET.Pro", SysFlag=YesNoEnum.Y, Remark="水印内容", OrderNo=330, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000341, Name="版权说明", Code=ConfigConst.SysWebCopyright, Value="Copyright © 2021-present Admin.NET All rights reserved.", SysFlag=YesNoEnum.Y, Remark="版权说明", OrderNo=340, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000351, Name="系统图标", Code=ConfigConst.SysWebLogo, Value="/Upload/logo.png", SysFlag=YesNoEnum.Y, Remark="系统图标", OrderNo=350, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000361, Name="ICP备案号", Code=ConfigConst.SysWebIcp, Value="省ICP备12345678号", SysFlag=YesNoEnum.Y, Remark="ICP备案号", OrderNo=360, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000371, Name="ICP地址", Code=ConfigConst.SysWebIcpUrl, Value="https://beian.miit.gov.cn", SysFlag=YesNoEnum.Y, Remark="ICP地址", OrderNo=370, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -65,12 +65,12 @@ public class SysAuthService : IDynamicApiController, ITransient
|
||||
// 判断密码错误次数(缓存30分钟)
|
||||
var keyPasswordErrorTimes = $"{CacheConst.KeyPasswordErrorTimes}{input.Account}";
|
||||
var passwordErrorTimes = _sysCacheService.Get<int>(keyPasswordErrorTimes);
|
||||
var passwdMaxErrorTimes = await _sysConfigService.GetConfigValue<int>(CommonConst.SysPasswordMaxErrorTimes);
|
||||
var passwdMaxErrorTimes = await _sysConfigService.GetConfigValue<int>(ConfigConst.SysPasswordMaxErrorTimes);
|
||||
if (passwordErrorTimes >= passwdMaxErrorTimes)
|
||||
throw Oops.Oh(ErrorCodeEnum.D1027);
|
||||
|
||||
// 是否开启验证码
|
||||
if (await _sysConfigService.GetConfigValue<bool>(CommonConst.SysCaptcha))
|
||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysCaptcha))
|
||||
{
|
||||
// 判断验证码
|
||||
if (!_captcha.Validate(input.CodeId.ToString(), input.Code))
|
||||
@ -101,7 +101,7 @@ public class SysAuthService : IDynamicApiController, ITransient
|
||||
}
|
||||
|
||||
// 是否开启域登录验证
|
||||
if (await _sysConfigService.GetConfigValue<bool>(CommonConst.SysDomainLogin))
|
||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysDomainLogin))
|
||||
{
|
||||
var userLdap = await _sysUserLdap.GetFirstAsync(u => u.UserId == user.Id && u.TenantId == tenant.Id);
|
||||
if (userLdap == null)
|
||||
@ -275,9 +275,9 @@ public class SysAuthService : IDynamicApiController, ITransient
|
||||
var roleIds = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysUserRole>>().AsQueryable()
|
||||
.Where(u => u.UserId == user.Id).Select(u => u.RoleId).ToListAsync();
|
||||
// 获取水印文字(若系统水印为空则全局为空)
|
||||
var watermarkText = await _sysConfigService.GetConfigValue<string>("sys_web_watermark");
|
||||
var watermarkText = await _sysConfigService.GetConfigValue<string>(ConfigConst.SysWebWatermark);
|
||||
if (!string.IsNullOrWhiteSpace(watermarkText))
|
||||
watermarkText += $"-{user.RealName}"; // $"-{user.RealName}-{_httpContextAccessor.HttpContext.GetRemoteIp()}-{DateTime.Now}";
|
||||
watermarkText += $"-{user.RealName}"; // $"-{user.RealName}-{_httpContextAccessor.HttpContext.GetRemoteIpAddressToIPv4(true)}-{DateTime.Now}";
|
||||
|
||||
return new LoginUserOutput
|
||||
{
|
||||
@ -334,23 +334,11 @@ public class SysAuthService : IDynamicApiController, ITransient
|
||||
[DisplayName("获取登录配置")]
|
||||
public async Task<dynamic> GetLoginConfig()
|
||||
{
|
||||
var secondVerEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysSecondVer);
|
||||
var captchaEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysCaptcha);
|
||||
var secondVerEnabled = await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSecondVer);
|
||||
var captchaEnabled = await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysCaptcha);
|
||||
return new { SecondVerEnabled = secondVerEnabled, CaptchaEnabled = captchaEnabled };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取水印配置 🔖
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[SuppressMonitor]
|
||||
[DisplayName("获取水印配置")]
|
||||
public async Task<dynamic> GetWatermarkConfig()
|
||||
{
|
||||
var watermarkEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysWatermark);
|
||||
return new { WatermarkEnabled = watermarkEnabled };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取验证码 🔖
|
||||
/// </summary>
|
||||
@ -389,7 +377,7 @@ public class SysAuthService : IDynamicApiController, ITransient
|
||||
{
|
||||
try
|
||||
{
|
||||
_sysCacheService.Set($"{CacheConst.KeyConfig}{CommonConst.SysCaptcha}", false);
|
||||
_sysCacheService.Set($"{CacheConst.KeyConfig}{ConfigConst.SysCaptcha}", false);
|
||||
|
||||
await Login(new LoginInput
|
||||
{
|
||||
@ -397,7 +385,7 @@ public class SysAuthService : IDynamicApiController, ITransient
|
||||
Password = CryptogramUtil.SM2Encrypt(auth.Password),
|
||||
});
|
||||
|
||||
_sysCacheService.Remove($"{CacheConst.KeyConfig}{CommonConst.SysCaptcha}");
|
||||
_sysCacheService.Remove($"{CacheConst.KeyConfig}{ConfigConst.SysCaptcha}");
|
||||
|
||||
return 200;
|
||||
}
|
||||
|
||||
@ -144,6 +144,10 @@ public class SysCacheService : IDynamicApiController, ISingleton
|
||||
[DisplayName("获取缓存值")]
|
||||
public object GetValue(string key)
|
||||
{
|
||||
// 若Key经过URL编码则进行解码
|
||||
if (Regex.IsMatch(key, @"%[0-9a-fA-F]{2}"))
|
||||
key = HttpUtility.UrlDecode(key);
|
||||
|
||||
return _cacheProvider.Cache == Cache.Default
|
||||
? _cacheProvider.Cache.Get<object>($"{_cacheOptions.Prefix}{key}")
|
||||
: _cacheProvider.Cache.Get<string>($"{_cacheOptions.Prefix}{key}");
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
using Hardware.Info;
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
@ -121,4 +122,50 @@ public class SysCommonService : IDynamicApiController, ITransient
|
||||
}
|
||||
return apiList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载标记错误的临时 Excel(全局) 🔖
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[DisplayName("下载标记错误的临时 Excel")]
|
||||
public async Task<IActionResult> DownloadErrorExcelTemp([FromQuery] string fileName = null)
|
||||
{
|
||||
var userId = App.User?.FindFirst(ClaimConst.UserId)?.Value;
|
||||
var resultStream = App.GetRequiredService<SysCacheService>().Get<MemoryStream>(CacheConst.KeyExcelTemp + userId);
|
||||
|
||||
if (resultStream == null)
|
||||
throw Oops.Oh("错误标记文件已过期。");
|
||||
|
||||
return await Task.FromResult(new FileStreamResult(resultStream, "application/octet-stream")
|
||||
{
|
||||
FileDownloadName = $"{(string.IsNullOrEmpty(fileName) ? "错误标记_" + DateTime.Now.ToString("yyyyMMddhhmmss") : fileName)}.xlsx"
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取机器序列号 🔖
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetMachineSerialKey()
|
||||
{
|
||||
try
|
||||
{
|
||||
HardwareInfo hardwareInfo = new();
|
||||
hardwareInfo.RefreshBIOSList(); // 刷新 BIOS 信息
|
||||
hardwareInfo.RefreshMotherboardList(); // 刷新主板信息
|
||||
hardwareInfo.RefreshCPUList(false); // 刷新 CPU 信息
|
||||
|
||||
var biosSerialNumber = hardwareInfo.BiosList.MinBy(u => u.SerialNumber)?.SerialNumber;
|
||||
var mbSerialNumber = hardwareInfo.MotherboardList.MinBy(u => u.SerialNumber)?.SerialNumber;
|
||||
var cpuProcessorId = hardwareInfo.CpuList.MinBy(u => u.ProcessorId)?.ProcessorId;
|
||||
// 根据 BIOS、主板和 CPU 信息生成 MD5 摘要
|
||||
var md5Data = MD5Encryption.Encrypt($"{biosSerialNumber}_{mbSerialNumber}_{cpuProcessorId}", true);
|
||||
var serialKey = $"{md5Data[..8]}-{md5Data[8..16]}-{md5Data[16..24]}-{md5Data[24..]}";
|
||||
return serialKey;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw Oops.Oh($"获取机器码失败:{ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -16,6 +16,11 @@ public class InfoSaveInput
|
||||
/// </summary>
|
||||
public string SysLogoBase64 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 系统图标文件名
|
||||
/// </summary>
|
||||
public string SysLogoFileName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 系统主标题
|
||||
/// </summary>
|
||||
|
||||
@ -14,15 +14,12 @@ public class SysConfigService : IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly SysCacheService _sysCacheService;
|
||||
private readonly SqlSugarRepository<SysConfig> _sysConfigRep;
|
||||
private readonly UserManager _userManager;
|
||||
|
||||
public SysConfigService(SysCacheService sysCacheService,
|
||||
SqlSugarRepository<SysConfig> sysConfigRep,
|
||||
UserManager userManager)
|
||||
SqlSugarRepository<SysConfig> sysConfigRep)
|
||||
{
|
||||
_sysCacheService = sysCacheService;
|
||||
_sysConfigRep = sysConfigRep;
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -34,7 +31,7 @@ public class SysConfigService : IDynamicApiController, ITransient
|
||||
public async Task<SqlSugarPagedList<SysConfig>> Page(PageConfigInput input)
|
||||
{
|
||||
return await _sysConfigRep.AsQueryable()
|
||||
.WhereIF(!_userManager.SuperAdmin, u => u.GroupCode != "WebConfig") // 若非超管,不显示 WebConfig 分组
|
||||
.Where(u => u.GroupCode != ConfigConst.SysWebConfigGroup) // 不显示 WebConfig 分组
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(input.Name?.Trim()), u => u.Name.Contains(input.Name))
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(input.Code?.Trim()), u => u.Code.Contains(input.Code))
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(input.GroupCode?.Trim()), u => u.GroupCode.Equals(input.GroupCode))
|
||||
@ -186,7 +183,7 @@ public class SysConfigService : IDynamicApiController, ITransient
|
||||
public async Task<List<string>> GetGroupList()
|
||||
{
|
||||
return await _sysConfigRep.AsQueryable()
|
||||
.Where(u => u.GroupCode != "WebConfig") // 不显示 WebConfig 分组
|
||||
.Where(u => u.GroupCode != ConfigConst.SysWebConfigGroup) // 不显示 WebConfig 分组
|
||||
.GroupBy(u => u.GroupCode)
|
||||
.Select(u => u.GroupCode).ToListAsync();
|
||||
}
|
||||
@ -198,7 +195,7 @@ public class SysConfigService : IDynamicApiController, ITransient
|
||||
[NonAction]
|
||||
public async Task<int> GetTokenExpire()
|
||||
{
|
||||
var tokenExpireStr = await GetConfigValue<string>(CommonConst.SysTokenExpire);
|
||||
var tokenExpireStr = await GetConfigValue<string>(ConfigConst.SysTokenExpire);
|
||||
_ = int.TryParse(tokenExpireStr, out var tokenExpire);
|
||||
return tokenExpire == 0 ? 20 : tokenExpire;
|
||||
}
|
||||
@ -210,7 +207,7 @@ public class SysConfigService : IDynamicApiController, ITransient
|
||||
[NonAction]
|
||||
public async Task<int> GetRefreshTokenExpire()
|
||||
{
|
||||
var refreshTokenExpireStr = await GetConfigValue<string>(CommonConst.SysRefreshTokenExpire);
|
||||
var refreshTokenExpireStr = await GetConfigValue<string>(ConfigConst.SysRefreshTokenExpire);
|
||||
_ = int.TryParse(refreshTokenExpireStr, out var refreshTokenExpire);
|
||||
return refreshTokenExpire == 0 ? 40 : refreshTokenExpire;
|
||||
}
|
||||
@ -240,14 +237,14 @@ public class SysConfigService : IDynamicApiController, ITransient
|
||||
[DisplayName("获取系统信息")]
|
||||
public async Task<dynamic> GetSysInfo()
|
||||
{
|
||||
var sysLogo = await GetConfigValue<string>("sys_web_logo");
|
||||
var sysTitle = await GetConfigValue<string>("sys_web_title");
|
||||
var sysViceTitle = await GetConfigValue<string>("sys_web_viceTitle");
|
||||
var sysViceDesc = await GetConfigValue<string>("sys_web_viceDesc");
|
||||
var sysWatermark = await GetConfigValue<string>("sys_web_watermark");
|
||||
var sysCopyright = await GetConfigValue<string>("sys_web_copyright");
|
||||
var sysIcp = await GetConfigValue<string>("sys_web_icp");
|
||||
var sysIcpUrl = await GetConfigValue<string>("sys_web_icpUrl");
|
||||
var sysLogo = await GetConfigValue<string>(ConfigConst.SysWebLogo);
|
||||
var sysTitle = await GetConfigValue<string>(ConfigConst.SysWebTitle);
|
||||
var sysViceTitle = await GetConfigValue<string>(ConfigConst.SysWebViceTitle);
|
||||
var sysViceDesc = await GetConfigValue<string>(ConfigConst.SysWebViceDesc);
|
||||
var sysWatermark = await GetConfigValue<string>(ConfigConst.SysWebWatermark);
|
||||
var sysCopyright = await GetConfigValue<string>(ConfigConst.SysWebCopyright);
|
||||
var sysIcp = await GetConfigValue<string>(ConfigConst.SysWebIcp);
|
||||
var sysIcpUrl = await GetConfigValue<string>(ConfigConst.SysWebIcpUrl);
|
||||
|
||||
return new
|
||||
{
|
||||
@ -266,6 +263,7 @@ public class SysConfigService : IDynamicApiController, ITransient
|
||||
/// 保存系统信息 🔖
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[UnitOfWork]
|
||||
[DisplayName("保存系统信息")]
|
||||
public async Task SaveSysInfo(InfoSaveInput input)
|
||||
{
|
||||
@ -273,17 +271,18 @@ public class SysConfigService : IDynamicApiController, ITransient
|
||||
if (!string.IsNullOrEmpty(input.SysLogoBase64))
|
||||
{
|
||||
// 旧图标文件相对路径
|
||||
var oldSysLogoRelativeFilePath = await GetConfigValue<string>("sys_web_logo") ?? "";
|
||||
var oldSysLogoRelativeFilePath = await GetConfigValue<string>(ConfigConst.SysWebLogo) ?? "";
|
||||
var oldSysLogoAbsoluteFilePath = Path.Combine(App.WebHostEnvironment.WebRootPath, oldSysLogoRelativeFilePath.TrimStart('/'));
|
||||
|
||||
var groups = Regex.Match(input.SysLogoBase64, @"data:image/(?<type>.+?);base64,(?<data>.+)").Groups;
|
||||
var type = groups["type"].Value;
|
||||
//var type = groups["type"].Value;
|
||||
var base64Data = groups["data"].Value;
|
||||
var binData = Convert.FromBase64String(base64Data);
|
||||
|
||||
// 根据文件名取扩展名
|
||||
var ext = string.IsNullOrWhiteSpace(input.SysLogoFileName) ? ".png" : Path.GetExtension(input.SysLogoFileName);
|
||||
// 本地图标保存路径
|
||||
var path = "Upload";
|
||||
var absoluteFilePath = Path.Combine(App.WebHostEnvironment.WebRootPath, path, $"logo.{type}");
|
||||
var absoluteFilePath = Path.Combine(App.WebHostEnvironment.WebRootPath, path, $"logo{ext}");
|
||||
|
||||
// 删除已存在文件
|
||||
if (File.Exists(oldSysLogoAbsoluteFilePath))
|
||||
@ -298,16 +297,16 @@ public class SysConfigService : IDynamicApiController, ITransient
|
||||
await File.WriteAllBytesAsync(absoluteFilePath, binData);
|
||||
|
||||
// 保存图标配置
|
||||
var relativeUrl = $"/{path}/logo.{type}";
|
||||
await UpdateConfigValue("sys_web_logo", relativeUrl);
|
||||
var relativeUrl = $"/{path}/logo{ext}";
|
||||
await UpdateConfigValue(ConfigConst.SysWebLogo, relativeUrl);
|
||||
}
|
||||
|
||||
await UpdateConfigValue("sys_web_title", input.SysTitle);
|
||||
await UpdateConfigValue("sys_web_viceTitle", input.SysViceTitle);
|
||||
await UpdateConfigValue("sys_web_viceDesc", input.SysViceDesc);
|
||||
await UpdateConfigValue("sys_web_watermark", input.SysWatermark);
|
||||
await UpdateConfigValue("sys_web_copyright", input.SysCopyright);
|
||||
await UpdateConfigValue("sys_web_icp", input.SysIcp);
|
||||
await UpdateConfigValue("sys_web_icpUrl", input.SysIcpUrl);
|
||||
await UpdateConfigValue(ConfigConst.SysWebTitle, input.SysTitle);
|
||||
await UpdateConfigValue(ConfigConst.SysWebViceTitle, input.SysViceTitle);
|
||||
await UpdateConfigValue(ConfigConst.SysWebViceDesc, input.SysViceDesc);
|
||||
await UpdateConfigValue(ConfigConst.SysWebWatermark, input.SysWatermark);
|
||||
await UpdateConfigValue(ConfigConst.SysWebCopyright, input.SysCopyright);
|
||||
await UpdateConfigValue(ConfigConst.SysWebIcp, input.SysIcp);
|
||||
await UpdateConfigValue(ConfigConst.SysWebIcpUrl, input.SysIcpUrl);
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,7 @@ public class DictDataInput : BaseIdInput
|
||||
/// <summary>
|
||||
/// 状态
|
||||
/// </summary>
|
||||
[Dict("StatusEnum")]
|
||||
public StatusEnum Status { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ public class DictTypeInput : BaseIdInput
|
||||
/// <summary>
|
||||
/// 状态
|
||||
/// </summary>
|
||||
[Dict("StatusEnum")]
|
||||
public StatusEnum Status { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
@ -13,8 +13,8 @@ namespace Admin.NET.Core.Service;
|
||||
[AllowAnonymous]
|
||||
public class SysDictDataService : IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly SysCacheService _sysCacheService;
|
||||
private readonly SqlSugarRepository<SysDictData> _sysDictDataRep;
|
||||
private readonly SysCacheService _sysCacheService;
|
||||
|
||||
public SysDictDataService(SqlSugarRepository<SysDictData> sysDictDataRep,
|
||||
SysCacheService sysCacheService)
|
||||
@ -60,8 +60,10 @@ public class SysDictDataService : IDynamicApiController, ITransient
|
||||
public async Task AddDictData(AddDictDataInput input)
|
||||
{
|
||||
var isExist = await _sysDictDataRep.IsAnyAsync(u => u.Code == input.Code && u.DictTypeId == input.DictTypeId);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCodeEnum.D3003);
|
||||
if (isExist) throw Oops.Oh(ErrorCodeEnum.D3003);
|
||||
|
||||
var dictTypeCode = await _sysDictDataRep.AsQueryable().Where(u => u.DictTypeId == input.DictTypeId).Select(u => u.DictType.Code).FirstAsync();
|
||||
_sysCacheService.Remove($"{CacheConst.KeyDict}{dictTypeCode}");
|
||||
|
||||
await _sysDictDataRep.InsertAsync(input.Adapt<SysDictData>());
|
||||
}
|
||||
@ -98,9 +100,7 @@ public class SysDictDataService : IDynamicApiController, ITransient
|
||||
[DisplayName("删除字典值")]
|
||||
public async Task DeleteDictData(DeleteDictDataInput input)
|
||||
{
|
||||
var dictData = await _sysDictDataRep.GetFirstAsync(u => u.Id == input.Id);
|
||||
if (dictData == null)
|
||||
throw Oops.Oh(ErrorCodeEnum.D3004);
|
||||
var dictData = await _sysDictDataRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D3004);
|
||||
|
||||
var dictTypeCode = await _sysDictDataRep.AsQueryable().Where(u => u.DictTypeId == dictData.Id).Select(u => u.DictType.Code).FirstAsync();
|
||||
_sysCacheService.Remove($"{CacheConst.KeyDict}{dictTypeCode}");
|
||||
@ -128,18 +128,13 @@ public class SysDictDataService : IDynamicApiController, ITransient
|
||||
[DisplayName("修改字典值状态")]
|
||||
public async Task SetStatus(DictDataInput input)
|
||||
{
|
||||
var dictData = await _sysDictDataRep.GetFirstAsync(u => u.Id == input.Id);
|
||||
if (dictData == null)
|
||||
throw Oops.Oh(ErrorCodeEnum.D3004);
|
||||
|
||||
if (!Enum.IsDefined(typeof(StatusEnum), input.Status))
|
||||
throw Oops.Oh(ErrorCodeEnum.D3005);
|
||||
var dictData = await _sysDictDataRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D3004);
|
||||
|
||||
var dictTypeCode = await _sysDictDataRep.AsQueryable().Where(u => u.DictTypeId == dictData.Id).Select(u => u.DictType.Code).FirstAsync();
|
||||
_sysCacheService.Remove($"{CacheConst.KeyDict}{dictTypeCode}");
|
||||
|
||||
dictData.Status = input.Status;
|
||||
await _sysDictDataRep.UpdateAsync(dictData);
|
||||
await _sysDictDataRep.AsUpdateable(dictData).UpdateColumns(u => new { u.Status }, true).ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -156,13 +151,9 @@ public class SysDictDataService : IDynamicApiController, ITransient
|
||||
if (dictDataList == null)
|
||||
{
|
||||
dictDataList = await _sysDictDataRep.AsQueryable()
|
||||
.Where(u => u.DictTypeId == dictTypeId)
|
||||
.OrderBy(u => new { u.OrderNo, u.Code })
|
||||
.ToListAsync();
|
||||
|
||||
.Where(u => u.DictTypeId == dictTypeId).OrderBy(u => new { u.OrderNo, u.Code }).ToListAsync();
|
||||
_sysCacheService.Set($"{CacheConst.KeyDict}{dictType.Code}", dictDataList);
|
||||
}
|
||||
|
||||
return dictDataList;
|
||||
}
|
||||
|
||||
|
||||
@ -60,10 +60,7 @@ public class SysDictTypeService : IDynamicApiController, ITransient
|
||||
[DisplayName("获取字典类型-值列表")]
|
||||
public async Task<List<SysDictData>> GetDataList([FromQuery] GetDataDictTypeInput input)
|
||||
{
|
||||
var dictType = await _sysDictTypeRep.GetFirstAsync(u => u.Code == input.Code);
|
||||
if (dictType == null)
|
||||
throw Oops.Oh(ErrorCodeEnum.D3000);
|
||||
|
||||
var dictType = await _sysDictTypeRep.GetFirstAsync(u => u.Code == input.Code) ?? throw Oops.Oh(ErrorCodeEnum.D3000);
|
||||
return await _sysDictDataService.GetDictDataListByDictTypeId(dictType.Id);
|
||||
}
|
||||
|
||||
@ -77,8 +74,7 @@ public class SysDictTypeService : IDynamicApiController, ITransient
|
||||
public async Task AddDictType(AddDictTypeInput input)
|
||||
{
|
||||
var isExist = await _sysDictTypeRep.IsAnyAsync(u => u.Code == input.Code);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCodeEnum.D3001);
|
||||
if (isExist) throw Oops.Oh(ErrorCodeEnum.D3001);
|
||||
|
||||
await _sysDictTypeRep.InsertAsync(input.Adapt<SysDictType>());
|
||||
}
|
||||
@ -94,12 +90,10 @@ public class SysDictTypeService : IDynamicApiController, ITransient
|
||||
public async Task UpdateDictType(UpdateDictTypeInput input)
|
||||
{
|
||||
var isExist = await _sysDictTypeRep.IsAnyAsync(u => u.Id == input.Id);
|
||||
if (!isExist)
|
||||
throw Oops.Oh(ErrorCodeEnum.D3000);
|
||||
if (!isExist) throw Oops.Oh(ErrorCodeEnum.D3000);
|
||||
|
||||
isExist = await _sysDictTypeRep.IsAnyAsync(u => u.Code == input.Code && u.Id != input.Id);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCodeEnum.D3001);
|
||||
if (isExist) throw Oops.Oh(ErrorCodeEnum.D3001);
|
||||
|
||||
_sysCacheService.Remove($"{CacheConst.KeyDict}{input.Code}");
|
||||
await _sysDictTypeRep.UpdateAsync(input.Adapt<SysDictType>());
|
||||
@ -115,9 +109,7 @@ public class SysDictTypeService : IDynamicApiController, ITransient
|
||||
[DisplayName("删除字典类型")]
|
||||
public async Task DeleteDictType(DeleteDictTypeInput input)
|
||||
{
|
||||
var dictType = await _sysDictTypeRep.GetFirstAsync(u => u.Id == input.Id);
|
||||
if (dictType == null)
|
||||
throw Oops.Oh(ErrorCodeEnum.D3000);
|
||||
var dictType = await _sysDictTypeRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D3000);
|
||||
|
||||
// 删除字典值
|
||||
await _sysDictTypeRep.DeleteAsync(dictType);
|
||||
@ -144,17 +136,12 @@ public class SysDictTypeService : IDynamicApiController, ITransient
|
||||
[DisplayName("修改字典类型状态")]
|
||||
public async Task SetStatus(DictTypeInput input)
|
||||
{
|
||||
var dictType = await _sysDictTypeRep.GetFirstAsync(u => u.Id == input.Id);
|
||||
if (dictType == null)
|
||||
throw Oops.Oh(ErrorCodeEnum.D3000);
|
||||
|
||||
if (!Enum.IsDefined(typeof(StatusEnum), input.Status))
|
||||
throw Oops.Oh(ErrorCodeEnum.D3005);
|
||||
var dictType = await _sysDictTypeRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D3000);
|
||||
|
||||
_sysCacheService.Remove($"{CacheConst.KeyDict}{dictType.Code}");
|
||||
|
||||
dictType.Status = input.Status;
|
||||
await _sysDictTypeRep.UpdateAsync(dictType);
|
||||
await _sysDictTypeRep.AsUpdateable(dictType).UpdateColumns(u => new { u.Status }, true).ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -49,7 +49,7 @@ public class SysEnumService : IDynamicApiController, ITransient
|
||||
{
|
||||
string description = type.Name;
|
||||
var attrs = type.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
if (attrs.Any())
|
||||
if (attrs.Length != 0)
|
||||
{
|
||||
var att = ((DescriptionAttribute[])attrs)[0];
|
||||
description = att.Description;
|
||||
|
||||
@ -315,11 +315,11 @@ public class SysFileService : IDynamicApiController, ITransient
|
||||
|
||||
// 验证文件类型
|
||||
if (!_uploadOptions.ContentType.Contains(file.ContentType))
|
||||
throw Oops.Oh(ErrorCodeEnum.D8001);
|
||||
throw Oops.Oh($"{ErrorCodeEnum.D8001}:{file.ContentType}");
|
||||
|
||||
// 验证文件大小
|
||||
if (sizeKb > _uploadOptions.MaxSize)
|
||||
throw Oops.Oh(ErrorCodeEnum.D8002);
|
||||
throw Oops.Oh($"{ErrorCodeEnum.D8002},允许最大:{_uploadOptions.MaxSize}KB");
|
||||
|
||||
// 获取文件后缀
|
||||
var suffix = Path.GetExtension(file.FileName).ToLower(); // 后缀
|
||||
|
||||
@ -42,14 +42,14 @@ public class DbJobPersistence : IJobPersistence
|
||||
var jobBuilder = schedulerBuilder.GetJobBuilder();
|
||||
|
||||
// 加载数据库数据
|
||||
var dbDetail = await db.Queryable<SysJobDetail>().FirstAsync(u => u.JobId == jobBuilder.JobId);
|
||||
var dbDetail = await db.Queryable<SysJobDetail>().FirstAsync(u => u.JobId == jobBuilder.JobId, stoppingToken);
|
||||
if (dbDetail == null) continue;
|
||||
|
||||
// 同步数据库数据
|
||||
jobBuilder.LoadFrom(dbDetail);
|
||||
|
||||
// 获取作业的所有数据库的触发器
|
||||
var dbTriggers = await db.Queryable<SysJobTrigger>().Where(u => u.JobId == jobBuilder.JobId).ToListAsync();
|
||||
var dbTriggers = await db.Queryable<SysJobTrigger>().Where(u => u.JobId == jobBuilder.JobId).ToListAsync(stoppingToken);
|
||||
// 遍历所有作业触发器
|
||||
foreach (var (_, triggerBuilder) in schedulerBuilder.GetEnumerable())
|
||||
{
|
||||
@ -73,24 +73,16 @@ public class DbJobPersistence : IJobPersistence
|
||||
}
|
||||
|
||||
// 获取数据库所有通过脚本创建的作业
|
||||
var allDbScriptJobs = await db.Queryable<SysJobDetail>().Where(u => u.CreateType != JobCreateTypeEnum.BuiltIn).ToListAsync();
|
||||
var allDbScriptJobs = await db.Queryable<SysJobDetail>().Where(u => u.CreateType != JobCreateTypeEnum.BuiltIn).ToListAsync(stoppingToken);
|
||||
foreach (var dbDetail in allDbScriptJobs)
|
||||
{
|
||||
// 动态创建作业
|
||||
Type jobType;
|
||||
switch (dbDetail.CreateType)
|
||||
Type jobType = dbDetail.CreateType switch
|
||||
{
|
||||
case JobCreateTypeEnum.Script:
|
||||
jobType = dynamicJobCompiler.BuildJob(dbDetail.ScriptCode);
|
||||
break;
|
||||
|
||||
case JobCreateTypeEnum.Http:
|
||||
jobType = typeof(HttpJob);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
JobCreateTypeEnum.Script => dynamicJobCompiler.BuildJob(dbDetail.ScriptCode),
|
||||
JobCreateTypeEnum.Http => typeof(HttpJob),
|
||||
_ => throw new NotSupportedException(),
|
||||
};
|
||||
|
||||
// 动态构建的 jobType 的程序集名称为随机名称,需重新设置
|
||||
dbDetail.AssemblyName = jobType.Assembly.FullName!.Split(',')[0];
|
||||
@ -131,25 +123,23 @@ public class DbJobPersistence : IJobPersistence
|
||||
/// <returns></returns>
|
||||
public async Task OnChangedAsync(PersistenceContext context)
|
||||
{
|
||||
using (var scope = _serviceScopeFactory.CreateScope())
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
|
||||
|
||||
var jobDetail = context.JobDetail.Adapt<SysJobDetail>();
|
||||
switch (context.Behavior)
|
||||
{
|
||||
var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
|
||||
case PersistenceBehavior.Appended:
|
||||
await db.Insertable(jobDetail).ExecuteCommandAsync();
|
||||
break;
|
||||
|
||||
var jobDetail = context.JobDetail.Adapt<SysJobDetail>();
|
||||
switch (context.Behavior)
|
||||
{
|
||||
case PersistenceBehavior.Appended:
|
||||
await db.Insertable(jobDetail).ExecuteCommandAsync();
|
||||
break;
|
||||
case PersistenceBehavior.Updated:
|
||||
await db.Updateable(jobDetail).WhereColumns(u => new { u.JobId }).IgnoreColumns(u => new { u.Id, u.CreateType, u.ScriptCode }).ExecuteCommandAsync();
|
||||
break;
|
||||
|
||||
case PersistenceBehavior.Updated:
|
||||
await db.Updateable(jobDetail).WhereColumns(u => new { u.JobId }).IgnoreColumns(u => new { u.Id, u.CreateType, u.ScriptCode }).ExecuteCommandAsync();
|
||||
break;
|
||||
|
||||
case PersistenceBehavior.Removed:
|
||||
await db.Deleteable<SysJobDetail>().Where(u => u.JobId == jobDetail.JobId).ExecuteCommandAsync();
|
||||
break;
|
||||
}
|
||||
case PersistenceBehavior.Removed:
|
||||
await db.Deleteable<SysJobDetail>().Where(u => u.JobId == jobDetail.JobId).ExecuteCommandAsync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,25 +150,23 @@ public class DbJobPersistence : IJobPersistence
|
||||
/// <returns></returns>
|
||||
public async Task OnTriggerChangedAsync(PersistenceTriggerContext context)
|
||||
{
|
||||
using (var scope = _serviceScopeFactory.CreateScope())
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
|
||||
|
||||
var jobTrigger = context.Trigger.Adapt<SysJobTrigger>();
|
||||
switch (context.Behavior)
|
||||
{
|
||||
var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
|
||||
case PersistenceBehavior.Appended:
|
||||
await db.Insertable(jobTrigger).ExecuteCommandAsync();
|
||||
break;
|
||||
|
||||
var jobTrigger = context.Trigger.Adapt<SysJobTrigger>();
|
||||
switch (context.Behavior)
|
||||
{
|
||||
case PersistenceBehavior.Appended:
|
||||
await db.Insertable(jobTrigger).ExecuteCommandAsync();
|
||||
break;
|
||||
case PersistenceBehavior.Updated:
|
||||
await db.Updateable(jobTrigger).WhereColumns(u => new { u.TriggerId, u.JobId }).IgnoreColumns(u => new { u.Id }).ExecuteCommandAsync();
|
||||
break;
|
||||
|
||||
case PersistenceBehavior.Updated:
|
||||
await db.Updateable(jobTrigger).WhereColumns(u => new { u.TriggerId, u.JobId }).IgnoreColumns(u => new { u.Id }).ExecuteCommandAsync();
|
||||
break;
|
||||
|
||||
case PersistenceBehavior.Removed:
|
||||
await db.Deleteable<SysJobTrigger>().Where(u => u.TriggerId == jobTrigger.TriggerId && u.JobId == jobTrigger.JobId).ExecuteCommandAsync();
|
||||
break;
|
||||
}
|
||||
case PersistenceBehavior.Removed:
|
||||
await db.Deleteable<SysJobTrigger>().Where(u => u.TriggerId == jobTrigger.TriggerId && u.JobId == jobTrigger.JobId).ExecuteCommandAsync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,12 +177,10 @@ public class DbJobPersistence : IJobPersistence
|
||||
/// <returns></returns>
|
||||
public async Task OnExecutionRecordAsync(PersistenceExecutionRecordContext context)
|
||||
{
|
||||
using (var scope = _serviceScopeFactory.CreateScope())
|
||||
{
|
||||
var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
|
||||
|
||||
var jobTriggerRecord = context.Timeline.Adapt<SysJobTriggerRecord>();
|
||||
await db.Insertable(jobTriggerRecord).ExecuteCommandAsync();
|
||||
}
|
||||
var jobTriggerRecord = context.Timeline.Adapt<SysJobTriggerRecord>();
|
||||
await db.Insertable(jobTriggerRecord).ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
|
||||
@ -30,10 +30,10 @@ public class JobMonitor : IJobMonitor
|
||||
public async Task OnExecutedAsync(JobExecutedContext context, CancellationToken stoppingToken)
|
||||
{
|
||||
// 将异常作业发送到邮件
|
||||
if (await _sysConfigService.GetConfigValue<bool>(CommonConst.SysErrorMail) && context.Exception != null)
|
||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysErrorMail) && context.Exception != null)
|
||||
{
|
||||
var errorInfo = $"【{context.Trigger.Description}】定时任务错误:{context.Exception}";
|
||||
await _eventPublisher.PublishAsync(CommonConst.SendErrorMail, errorInfo);
|
||||
await _eventPublisher.PublishAsync(CommonConst.SendErrorMail, errorInfo, stoppingToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -59,7 +59,7 @@ public class SysMenuService : IDynamicApiController, ITransient
|
||||
/// <summary>
|
||||
/// 删除登录菜单树里面的按钮
|
||||
/// </summary>
|
||||
private void DeleteBtnFromMenuTree(List<SysMenu> menuList)
|
||||
private static void DeleteBtnFromMenuTree(List<SysMenu> menuList)
|
||||
{
|
||||
if (menuList == null) return;
|
||||
for (var i = menuList.Count - 1; i >= 0; i--)
|
||||
|
||||
@ -16,10 +16,12 @@ namespace Admin.NET.Core.Service;
|
||||
public class SysEmailService : IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly EmailOptions _emailOptions;
|
||||
private readonly SysConfigService _sysConfigService;
|
||||
|
||||
public SysEmailService(IOptions<EmailOptions> emailOptions)
|
||||
public SysEmailService(IOptions<EmailOptions> emailOptions, SysConfigService sysConfigService)
|
||||
{
|
||||
_emailOptions = emailOptions.Value;
|
||||
_sysConfigService = sysConfigService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -29,8 +31,10 @@ public class SysEmailService : IDynamicApiController, ITransient
|
||||
/// <param name="title"></param>
|
||||
/// <returns></returns>
|
||||
[DisplayName("发送邮件")]
|
||||
public async Task SendEmail([Required] string content, string title = "Admin.NET 系统邮件")
|
||||
public async Task SendEmail([Required] string content, string title = "")
|
||||
{
|
||||
var webTitle = await _sysConfigService.GetConfigValue<string>(ConfigConst.SysWebTitle);
|
||||
title = string.IsNullOrWhiteSpace(title) ? $"{webTitle} 系统邮件" : title;
|
||||
var message = new MimeMessage();
|
||||
message.From.Add(new MailboxAddress(_emailOptions.DefaultFromEmail, _emailOptions.DefaultFromEmail));
|
||||
message.To.Add(new MailboxAddress(_emailOptions.DefaultToEmail, _emailOptions.DefaultToEmail));
|
||||
|
||||
@ -48,7 +48,7 @@ public class SysMessageService : IDynamicApiController, ITransient
|
||||
{
|
||||
var cacheKey = CacheConst.KeyUserOnline + input.ReceiveUserId;
|
||||
// 是否开启单用户登录
|
||||
if (await _sysConfigService.GetConfigValue<bool>(CommonConst.SysSingleLogin))
|
||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
||||
{
|
||||
var user = _sysCacheService.Get<SysOnlineUser>(cacheKey);
|
||||
if (user == null) return;
|
||||
@ -76,7 +76,7 @@ public class SysMessageService : IDynamicApiController, ITransient
|
||||
{
|
||||
var cacheKey = CacheConst.KeyUserOnline + input.ReceiveUserId;
|
||||
// 是否开启单用户登录
|
||||
if (await _sysConfigService.GetConfigValue<bool>(CommonConst.SysSingleLogin))
|
||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
||||
{
|
||||
var user = _sysCacheService.Get<SysOnlineUser>(cacheKey);
|
||||
if (user == null) return;
|
||||
@ -107,7 +107,7 @@ public class SysMessageService : IDynamicApiController, ITransient
|
||||
{
|
||||
var cacheKey = CacheConst.KeyUserOnline + userId;
|
||||
// 是否开启单用户登录
|
||||
if (await _sysConfigService.GetConfigValue<bool>(CommonConst.SysSingleLogin))
|
||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
||||
{
|
||||
var user = _sysCacheService.Get<SysOnlineUser>(cacheKey);
|
||||
if (user != null) userList.Add(user.ConnectionId);
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
|
||||
namespace Admin.NET.Core.Service;
|
||||
|
||||
public static class HttpContextExtension
|
||||
{
|
||||
public static async Task<AuthenticationScheme[]> GetExternalProvidersAsync(this HttpContext context)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
|
||||
var schemes = context.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||
|
||||
return (from scheme in await schemes.GetAllSchemesAsync()
|
||||
where !string.IsNullOrEmpty(scheme.DisplayName)
|
||||
select scheme).ToArray();
|
||||
}
|
||||
|
||||
public static async Task<bool> IsProviderSupportedAsync(this HttpContext context, string provider)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
|
||||
return (from scheme in await context.GetExternalProvidersAsync()
|
||||
where string.Equals(scheme.Name, provider, StringComparison.OrdinalIgnoreCase)
|
||||
select scheme).Any();
|
||||
}
|
||||
}
|
||||
@ -78,7 +78,7 @@ public class SysOnlineUserService : IDynamicApiController, ITransient
|
||||
[NonAction]
|
||||
public async Task SingleLogin(long userId)
|
||||
{
|
||||
if (await _sysConfigService.GetConfigValue<bool>(CommonConst.SysSingleLogin))
|
||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
||||
{
|
||||
var users = await _sysOnlineUerRep.GetListAsync(u => u.UserId == userId);
|
||||
foreach (var user in users)
|
||||
|
||||
@ -4,6 +4,9 @@
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
using AngleSharp;
|
||||
using AngleSharp.Html.Dom;
|
||||
|
||||
namespace Admin.NET.Core.Service;
|
||||
|
||||
/// <summary>
|
||||
@ -13,13 +16,15 @@ namespace Admin.NET.Core.Service;
|
||||
public class SysRegionService : IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly SqlSugarRepository<SysRegion> _sysRegionRep;
|
||||
private readonly SysConfigService _sysConfigService;
|
||||
|
||||
//// Url地址-国家统计局行政区域2023年
|
||||
//private readonly string _url = "http://www.stats.gov.cn/sj/tjbz/tjyqhdmhcxhfdm/2023/index.html";
|
||||
// Url地址-国家统计局行政区域2023年
|
||||
private readonly string _url = "http://www.stats.gov.cn/sj/tjbz/tjyqhdmhcxhfdm/2023/index.html";
|
||||
|
||||
public SysRegionService(SqlSugarRepository<SysRegion> sysRegionRep)
|
||||
public SysRegionService(SqlSugarRepository<SysRegion> sysRegionRep, SysConfigService sysConfigService)
|
||||
{
|
||||
_sysRegionRep = sysRegionRep;
|
||||
_sysConfigService = sysConfigService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -59,7 +64,7 @@ public class SysRegionService : IDynamicApiController, ITransient
|
||||
{
|
||||
input.Code = input.Code.Trim();
|
||||
if (input.Code.Length != 12 && input.Code.Length != 9 && input.Code.Length != 6)
|
||||
throw Oops.Oh("行政区代码只能为6、9或12位");
|
||||
throw Oops.Oh(ErrorCodeEnum.R2003);
|
||||
|
||||
if (input.Pid != 0)
|
||||
{
|
||||
@ -90,9 +95,13 @@ public class SysRegionService : IDynamicApiController, ITransient
|
||||
{
|
||||
input.Code = input.Code.Trim();
|
||||
if (input.Code.Length != 12 && input.Code.Length != 9 && input.Code.Length != 6)
|
||||
throw Oops.Oh("行政区代码只能为6、9或12位");
|
||||
throw Oops.Oh(ErrorCodeEnum.R2003);
|
||||
|
||||
if (input.Pid != input.Pid && input.Pid != 0)
|
||||
var sysRegion = await _sysRegionRep.GetFirstAsync(u => u.Id == input.Id);
|
||||
if (sysRegion == null)
|
||||
throw Oops.Oh(ErrorCodeEnum.D1002);
|
||||
|
||||
if (sysRegion.Pid != input.Pid && input.Pid != 0)
|
||||
{
|
||||
var pRegion = await _sysRegionRep.GetFirstAsync(u => u.Id == input.Pid);
|
||||
pRegion ??= await _sysRegionRep.GetFirstAsync(u => u.Code == input.Pid.ToString());
|
||||
@ -103,13 +112,12 @@ public class SysRegionService : IDynamicApiController, ITransient
|
||||
var regionTreeList = await _sysRegionRep.AsQueryable().ToChildListAsync(u => u.Pid, input.Id, true);
|
||||
var childIdList = regionTreeList.Select(u => u.Id).ToList();
|
||||
if (childIdList.Contains(input.Pid))
|
||||
throw Oops.Oh("父节点不能为自己的子节点");
|
||||
throw Oops.Oh(ErrorCodeEnum.R2004);
|
||||
}
|
||||
|
||||
if (input.Id == input.Pid)
|
||||
throw Oops.Oh(ErrorCodeEnum.R2001);
|
||||
|
||||
var sysRegion = await _sysRegionRep.GetFirstAsync(u => u.Id == input.Id);
|
||||
var isExist = await _sysRegionRep.IsAnyAsync(u => (u.Name == input.Name && u.Code == input.Code) && u.Id != sysRegion.Id);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCodeEnum.R2002);
|
||||
@ -144,93 +152,117 @@ public class SysRegionService : IDynamicApiController, ITransient
|
||||
[DisplayName("同步行政区域")]
|
||||
public async Task Sync()
|
||||
{
|
||||
var syncLevel = await _sysConfigService.GetConfigValue<int>(ConfigConst.SysRegionSyncLevel);
|
||||
if (syncLevel < 1 || syncLevel > 5)
|
||||
syncLevel = 3;//默认区县级
|
||||
var context = BrowsingContext.New(AngleSharp.Configuration.Default.WithDefaultLoader());
|
||||
var dom = await context.OpenAsync(_url);
|
||||
|
||||
// 省级
|
||||
var itemList = dom.QuerySelectorAll("table.provincetable tr.provincetr td a");
|
||||
if (itemList.Length == 0)
|
||||
throw Oops.Oh(ErrorCodeEnum.R2005);
|
||||
|
||||
await _sysRegionRep.DeleteAsync(u => u.Id > 0);
|
||||
|
||||
//var context = BrowsingContext.New(AngleSharp.Configuration.Default.WithDefaultLoader());
|
||||
//var dom = await context.OpenAsync(_url);
|
||||
foreach (IHtmlAnchorElement item in itemList)
|
||||
{
|
||||
var list = new List<SysRegion>();
|
||||
|
||||
//// 省级
|
||||
//var itemList = dom.QuerySelectorAll("table.provincetable tr.provincetr td a");
|
||||
//foreach (IHtmlAnchorElement item in itemList)
|
||||
//{
|
||||
// var region = await _sysRegionRep.InsertReturnEntityAsync(new SysRegion
|
||||
// {
|
||||
// Pid = 0,
|
||||
// Name = item.TextContent,
|
||||
// Remark = item.Href,
|
||||
// Level = 1,
|
||||
// });
|
||||
var region = new SysRegion
|
||||
{
|
||||
Id = YitIdHelper.NextId(),
|
||||
Pid = 0,
|
||||
Name = item.TextContent,
|
||||
Remark = item.Href,
|
||||
Level = 1,
|
||||
};
|
||||
list.Add(region);
|
||||
|
||||
// // 市级
|
||||
// if (string.IsNullOrEmpty(item.Href))
|
||||
// continue;
|
||||
// var dom1 = await context.OpenAsync(item.Href);
|
||||
// var itemList1 = dom1.QuerySelectorAll("table.citytable tr.citytr td a");
|
||||
// for (var i1 = 0; i1 < itemList1.Length; i1 += 2)
|
||||
// {
|
||||
// var item1 = (IHtmlAnchorElement)itemList1[i1 + 1];
|
||||
// var region1 = await _sysRegionRep.InsertReturnEntityAsync(new SysRegion
|
||||
// {
|
||||
// Pid = region.Id,
|
||||
// Name = item1.TextContent,
|
||||
// Code = itemList1[i1].TextContent,
|
||||
// Remark = item1.Href,
|
||||
// Level = 2,
|
||||
// });
|
||||
// 市级
|
||||
if (!string.IsNullOrEmpty(item.Href) && syncLevel > 1)
|
||||
{
|
||||
var dom1 = await context.OpenAsync(item.Href);
|
||||
var itemList1 = dom1.QuerySelectorAll("table.citytable tr.citytr td a");
|
||||
for (var i1 = 0; i1 < itemList1.Length; i1 += 2)
|
||||
{
|
||||
var item1 = (IHtmlAnchorElement)itemList1[i1 + 1];
|
||||
var region1 = new SysRegion
|
||||
{
|
||||
Id = YitIdHelper.NextId(),
|
||||
Pid = region.Id,
|
||||
Name = item1.TextContent,
|
||||
Code = itemList1[i1].TextContent,
|
||||
Remark = item1.Href,
|
||||
Level = 2,
|
||||
};
|
||||
list.Add(region1);
|
||||
|
||||
// // 区县级
|
||||
// if (string.IsNullOrEmpty(item1.Href))
|
||||
// continue;
|
||||
// var dom2 = await context.OpenAsync(item1.Href);
|
||||
// var itemList2 = dom2.QuerySelectorAll("table.countytable tr.countytr td a");
|
||||
// for (var i2 = 0; i2 < itemList2.Length; i2 += 2)
|
||||
// {
|
||||
// var item2 = (IHtmlAnchorElement)itemList2[i2 + 1];
|
||||
// var region2 = await _sysRegionRep.InsertReturnEntityAsync(new SysRegion
|
||||
// {
|
||||
// Pid = region1.Id,
|
||||
// Name = item2.TextContent,
|
||||
// Code = itemList2[i2].TextContent,
|
||||
// Remark = item2.Href,
|
||||
// Level = 3,
|
||||
// });
|
||||
// 区县级
|
||||
if (!string.IsNullOrEmpty(item1.Href) && syncLevel > 2)
|
||||
{
|
||||
var dom2 = await context.OpenAsync(item1.Href);
|
||||
var itemList2 = dom2.QuerySelectorAll("table.countytable tr.countytr td a");
|
||||
for (var i2 = 0; i2 < itemList2.Length; i2 += 2)
|
||||
{
|
||||
var item2 = (IHtmlAnchorElement)itemList2[i2 + 1];
|
||||
var region2 = new SysRegion
|
||||
{
|
||||
Id = YitIdHelper.NextId(),
|
||||
Pid = region1.Id,
|
||||
Name = item2.TextContent,
|
||||
Code = itemList2[i2].TextContent,
|
||||
Remark = item2.Href,
|
||||
Level = 3,
|
||||
};
|
||||
list.Add(region2);
|
||||
|
||||
// // 街道级
|
||||
// if (string.IsNullOrEmpty(item2.Href))
|
||||
// continue;
|
||||
// var dom3 = await context.OpenAsync(item2.Href);
|
||||
// var itemList3 = dom3.QuerySelectorAll("table.towntable tr.towntr td a");
|
||||
// for (var i3 = 0; i3 < itemList3.Length; i3 += 2)
|
||||
// {
|
||||
// var item3 = (IHtmlAnchorElement)itemList3[i3 + 1];
|
||||
// var region3 = await _sysRegionRep.InsertReturnEntityAsync(new SysRegion
|
||||
// {
|
||||
// Pid = region2.Id,
|
||||
// Name = item3.TextContent,
|
||||
// Code = itemList3[i3].TextContent,
|
||||
// Remark = item3.Href,
|
||||
// Level = 4,
|
||||
// });
|
||||
// 街道级
|
||||
if (!string.IsNullOrEmpty(item2.Href) && syncLevel > 3)
|
||||
{
|
||||
var dom3 = await context.OpenAsync(item2.Href);
|
||||
var itemList3 = dom3.QuerySelectorAll("table.towntable tr.towntr td a");
|
||||
for (var i3 = 0; i3 < itemList3.Length; i3 += 2)
|
||||
{
|
||||
var item3 = (IHtmlAnchorElement)itemList3[i3 + 1];
|
||||
var region3 = new SysRegion
|
||||
{
|
||||
Id = YitIdHelper.NextId(),
|
||||
Pid = region2.Id,
|
||||
Name = item3.TextContent,
|
||||
Code = itemList3[i3].TextContent,
|
||||
Remark = item3.Href,
|
||||
Level = 4,
|
||||
};
|
||||
list.Add(region3);
|
||||
|
||||
// // 村级
|
||||
// if (string.IsNullOrEmpty(item3.Href))
|
||||
// continue;
|
||||
// var dom4 = await context.OpenAsync(item3.Href);
|
||||
// var itemList4 = dom4.QuerySelectorAll("table.villagetable tr.villagetr td");
|
||||
// for (var i4 = 0; i4 < itemList4.Length; i4 += 3)
|
||||
// {
|
||||
// await _sysRegionRep.InsertAsync(new SysRegion
|
||||
// {
|
||||
// Pid = region3.Id,
|
||||
// Name = itemList4[i4 + 2].TextContent,
|
||||
// Code = itemList4[i4].TextContent,
|
||||
// CityCode = itemList4[i4 + 1].TextContent,
|
||||
// Level = 5,
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
// 村级
|
||||
if (!string.IsNullOrEmpty(item3.Href) && syncLevel > 4)
|
||||
{
|
||||
var dom4 = await context.OpenAsync(item3.Href);
|
||||
var itemList4 = dom4.QuerySelectorAll("table.villagetable tr.villagetr td");
|
||||
for (var i4 = 0; i4 < itemList4.Length; i4 += 3)
|
||||
{
|
||||
list.Add(new SysRegion
|
||||
{
|
||||
Id = YitIdHelper.NextId(),
|
||||
Pid = region3.Id,
|
||||
Name = itemList4[i4 + 2].TextContent,
|
||||
Code = itemList4[i4].TextContent,
|
||||
CityCode = itemList4[i4 + 1].TextContent,
|
||||
Level = 5,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//按省份同步快速写入提升同步效率,全部一次性写入容易出现从统计局获取数据失败
|
||||
_sysRegionRep.Context.Fastest<SysRegion>().BulkCopy(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -27,7 +27,7 @@ public class SysRoleApiService : ITransient
|
||||
{
|
||||
await _sysRoleApiRep.DeleteAsync(u => u.RoleId == input.Id);
|
||||
|
||||
var roleApis = input.ApiList.Select(u => new SysRoleApi
|
||||
var roleApis = input.ApiList.Where(u => !string.IsNullOrWhiteSpace(u)).Select(u => new SysRoleApi
|
||||
{
|
||||
RoleId = input.Id,
|
||||
Route = u
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core.Service;
|
||||
|
||||
public class ScheduleInput : BaseIdInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 状态
|
||||
/// </summary>
|
||||
public virtual FinishStatusEnum Status { get; set; }
|
||||
}
|
||||
|
||||
public class ListScheduleInput
|
||||
{
|
||||
public DateTime? StartTime { get; set; }
|
||||
|
||||
public DateTime? EndTime { get; set; }
|
||||
}
|
||||
|
||||
public class AddScheduleInput : SysSchedule
|
||||
{
|
||||
/// <summary>
|
||||
/// 日程内容
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "日程内容不能为空")]
|
||||
public override string Content { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateScheduleInput : AddScheduleInput
|
||||
{
|
||||
}
|
||||
|
||||
public class DeleteScheduleInput : BaseIdInput
|
||||
{
|
||||
}
|
||||
104
Admin.NET/Admin.NET.Core/Service/Schedule/SysScheduleService.cs
Normal file
104
Admin.NET/Admin.NET.Core/Service/Schedule/SysScheduleService.cs
Normal file
@ -0,0 +1,104 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core.Service;
|
||||
|
||||
/// <summary>
|
||||
/// 系统日程服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Order = 295)]
|
||||
public class SysScheduleService : IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly UserManager _userManager;
|
||||
private readonly SqlSugarRepository<SysSchedule> _sysSchedule;
|
||||
|
||||
public SysScheduleService(UserManager userManager,
|
||||
SqlSugarRepository<SysSchedule> sysSchedle)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_sysSchedule = sysSchedle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取日程列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[DisplayName("获取日程列表")]
|
||||
public async Task<List<SysSchedule>> Page(ListScheduleInput input)
|
||||
{
|
||||
return await _sysSchedule.AsQueryable()
|
||||
.Where(u => u.UserId == _userManager.UserId)
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()), u => u.ScheduleTime >= input.StartTime)
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(input.EndTime.ToString()), u => u.ScheduleTime <= input.EndTime)
|
||||
.OrderBy(u => u.StartTime, OrderByType.Asc)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取日程详情
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[DisplayName("获取日程详情")]
|
||||
public async Task<SysSchedule> GetDetail(long id)
|
||||
{
|
||||
return await _sysSchedule.GetFirstAsync(u => u.Id == id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加日程
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[ApiDescriptionSettings(Name = "Add"), HttpPost]
|
||||
[DisplayName("增加日程")]
|
||||
public async Task AddUserSchedule(AddScheduleInput input)
|
||||
{
|
||||
input.UserId = _userManager.UserId;
|
||||
await _sysSchedule.InsertAsync(input.Adapt<SysSchedule>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新日程
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[ApiDescriptionSettings(Name = "Update"), HttpPost]
|
||||
[DisplayName("更新日程")]
|
||||
public async Task UpdateUserSchedule(UpdateScheduleInput input)
|
||||
{
|
||||
await _sysSchedule.AsUpdateable(input.Adapt<SysSchedule>()).IgnoreColumns(true).ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除日程
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[ApiDescriptionSettings(Name = "Delete"), HttpPost]
|
||||
[DisplayName("删除日程")]
|
||||
public async Task DeleteUserSchedule(DeleteScheduleInput input)
|
||||
{
|
||||
await _sysSchedule.DeleteAsync(u => u.Id == input.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置日程状态
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[DisplayName("设置日程状态")]
|
||||
public async Task<int> SetStatus(ScheduleInput input)
|
||||
{
|
||||
if (!Enum.IsDefined(typeof(FinishStatusEnum), input.Status))
|
||||
throw Oops.Oh(ErrorCodeEnum.D3005);
|
||||
|
||||
return await _sysSchedule.AsUpdateable()
|
||||
.SetColumns(u => u.Status == input.Status)
|
||||
.Where(u => u.Id == input.Id)
|
||||
.ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
@ -210,7 +210,7 @@ public class SysTenantService : IDynamicApiController, ITransient
|
||||
await _sysPosRep.InsertAsync(newPos);
|
||||
|
||||
// 初始化系统账号
|
||||
var password = await _sysConfigService.GetConfigValue<string>(CommonConst.SysPassword);
|
||||
var password = await _sysConfigService.GetConfigValue<string>(ConfigConst.SysPassword);
|
||||
var newUser = new SysUser
|
||||
{
|
||||
Id = tenantId,
|
||||
@ -265,6 +265,11 @@ public class SysTenantService : IDynamicApiController, ITransient
|
||||
if (input.Id.ToString() == SqlSugarConst.MainConfigId)
|
||||
throw Oops.Oh(ErrorCodeEnum.D1023);
|
||||
|
||||
// 若账号为开放接口绑定租户则禁止删除
|
||||
var isOpenAccessTenant = await _sysTenantRep.ChangeRepository<SqlSugarRepository<SysOpenAccess>>().IsAnyAsync(u => u.BindTenantId == input.Id);
|
||||
if (isOpenAccessTenant)
|
||||
throw Oops.Oh(ErrorCodeEnum.D1031);
|
||||
|
||||
await _sysTenantRep.DeleteAsync(u => u.Id == input.Id);
|
||||
|
||||
await CacheTenant(input.Id);
|
||||
@ -375,7 +380,7 @@ public class SysTenantService : IDynamicApiController, ITransient
|
||||
[DisplayName("重置租户管理员密码")]
|
||||
public async Task<string> ResetPwd(TenantUserInput input)
|
||||
{
|
||||
var password = await _sysConfigService.GetConfigValue<string>(CommonConst.SysPassword);
|
||||
var password = await _sysConfigService.GetConfigValue<string>(ConfigConst.SysPassword);
|
||||
var encryptPassword = CryptogramUtil.Encrypt(password);
|
||||
await _sysUserRep.UpdateAsync(u => new SysUser() { Password = encryptPassword }, u => u.Id == input.UserId);
|
||||
return password;
|
||||
|
||||
@ -96,7 +96,7 @@ public class SysUserService : IDynamicApiController, ITransient
|
||||
var isExist = await _sysUserRep.AsQueryable().ClearFilter().AnyAsync(u => u.Account == input.Account);
|
||||
if (isExist) throw Oops.Oh(ErrorCodeEnum.D1003);
|
||||
|
||||
var password = await _sysConfigService.GetConfigValue<string>(CommonConst.SysPassword);
|
||||
var password = await _sysConfigService.GetConfigValue<string>(ConfigConst.SysPassword);
|
||||
|
||||
var user = input.Adapt<SysUser>();
|
||||
user.Password = CryptogramUtil.Encrypt(password);
|
||||
@ -172,11 +172,17 @@ public class SysUserService : IDynamicApiController, ITransient
|
||||
throw Oops.Oh(ErrorCodeEnum.D1014);
|
||||
if (user.Id == _userManager.UserId)
|
||||
throw Oops.Oh(ErrorCodeEnum.D1001);
|
||||
|
||||
// 若账号为租户默认账号则禁止删除
|
||||
var isTenantUser = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysTenant>>().IsAnyAsync(u => u.UserId == input.Id);
|
||||
if (isTenantUser)
|
||||
throw Oops.Oh(ErrorCodeEnum.D1029);
|
||||
|
||||
// 若账号为开放接口绑定账号则禁止删除
|
||||
var isOpenAccessUser = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysOpenAccess>>().IsAnyAsync(u => u.BindUserId == input.Id);
|
||||
if (isOpenAccessUser)
|
||||
throw Oops.Oh(ErrorCodeEnum.D1030);
|
||||
|
||||
// 强制下线
|
||||
await _sysOnlineUserService.ForceOffline(user.Id);
|
||||
|
||||
@ -317,7 +323,7 @@ public class SysUserService : IDynamicApiController, ITransient
|
||||
public virtual async Task<string> ResetPwd(ResetPwdUserInput input)
|
||||
{
|
||||
var user = await _sysUserRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D0009);
|
||||
var password = await _sysConfigService.GetConfigValue<string>(CommonConst.SysPassword);
|
||||
var password = await _sysConfigService.GetConfigValue<string>(ConfigConst.SysPassword);
|
||||
user.Password = CryptogramUtil.Encrypt(password);
|
||||
await _sysUserRep.AsUpdateable(user).UpdateColumns(u => u.Password).ExecuteCommandAsync();
|
||||
|
||||
|
||||
@ -115,4 +115,30 @@ public class AddSubscribeMessageTemplateInput
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "服务场景描述不能为空")]
|
||||
public string SceneDescription { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证签名
|
||||
/// </summary>
|
||||
public class VerifySignatureInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 签名
|
||||
/// </summary>
|
||||
public string Signature { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 时间戳
|
||||
/// </summary>
|
||||
public string Timestamp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 随机数
|
||||
/// </summary>
|
||||
public string Nonce { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 随机字符串
|
||||
/// </summary>
|
||||
public string Echostr { get; set; }
|
||||
}
|
||||
@ -114,6 +114,24 @@ public class SysWxOpenService : IDynamicApiController, ITransient
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证签名 🔖
|
||||
/// </summary>
|
||||
[AllowAnonymous]
|
||||
[NonUnify]
|
||||
[ApiDescriptionSettings(Name = "VerifySignature"), HttpGet]
|
||||
[DisplayName("验证签名")]
|
||||
public string VerifySignature([FromQuery] VerifySignatureInput input)
|
||||
{
|
||||
bool valid = _wechatApiClient.VerifyEventSignatureForEcho(input.Timestamp, input.Nonce, input.Signature);
|
||||
if (!valid)
|
||||
{
|
||||
return "fail";
|
||||
}
|
||||
|
||||
return input.Echostr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取订阅消息模板列表 🔖
|
||||
/// </summary>
|
||||
|
||||
@ -68,8 +68,10 @@ public static class SqlSugarFilter
|
||||
if ((tAtt != null && db.CurrentConnectionConfig.ConfigId.ToString() != tAtt.configId.ToString()))
|
||||
continue;
|
||||
|
||||
var lambda = DynamicExpressionParser.ParseLambda(new[] {
|
||||
Expression.Parameter(entityType, "u") }, typeof(bool), $"@0.Contains(u.{nameof(EntityBaseData.CreateOrgId)}??{default(long)})", orgIds);
|
||||
//var lambda = DynamicExpressionParser.ParseLambda(new[] {
|
||||
// Expression.Parameter(entityType, "u") }, typeof(bool), $"@0.Contains(u.{nameof(EntityBaseData.CreateOrgId)}??{default(long)})", orgIds);
|
||||
var lambda = entityType.GetConditionExpression<OwnerOrgAttribute>(orgIds);
|
||||
|
||||
db.QueryFilter.AddTableFilter(entityType, lambda);
|
||||
orgFilter.TryAdd(entityType, lambda);
|
||||
}
|
||||
@ -114,8 +116,10 @@ public static class SqlSugarFilter
|
||||
if ((tAtt != null && db.CurrentConnectionConfig.ConfigId.ToString() != tAtt.configId.ToString()))
|
||||
continue;
|
||||
|
||||
var lambda = DynamicExpressionParser.ParseLambda(new[] {
|
||||
Expression.Parameter(entityType, "u") }, typeof(bool), $"u.{nameof(EntityBaseData.CreateUserId)}=@0", userId);
|
||||
//var lambda = DynamicExpressionParser.ParseLambda(new[] {
|
||||
// Expression.Parameter(entityType, "u") }, typeof(bool), $"u.{nameof(EntityBaseData.CreateUserId)}=@0", userId);
|
||||
var lambda = entityType.GetConditionExpression<OwnerUserAttribute>(new List<long> { long.Parse(userId) });
|
||||
|
||||
db.QueryFilter.AddTableFilter(entityType, lambda);
|
||||
dataScopeFilter.TryAdd(entityType, lambda);
|
||||
}
|
||||
|
||||
@ -172,9 +172,11 @@ public static class SqlSugarSetup
|
||||
entityInfo.SetValue(YitIdHelper.NextId());
|
||||
}
|
||||
// 若创建时间为空则赋值当前时间
|
||||
else if (entityInfo.PropertyName == nameof(EntityBase.CreateTime) && entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue) == null)
|
||||
else if (entityInfo.PropertyName == nameof(EntityBase.CreateTime))
|
||||
{
|
||||
entityInfo.SetValue(DateTime.Now);
|
||||
var createTime = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue)!;
|
||||
if (createTime == null || createTime.Equals(DateTime.MinValue))
|
||||
entityInfo.SetValue(DateTime.Now);
|
||||
}
|
||||
// 若当前用户非空(web线程时)
|
||||
if (App.User != null)
|
||||
@ -314,7 +316,7 @@ public static class SqlSugarSetup
|
||||
{
|
||||
var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))))
|
||||
.WhereIF(config.SeedSettings.EnableIncreSeed, u => u.IsDefined(typeof(IncreSeedAttribute), false))
|
||||
.OrderBy(u => u.GetCustomAttributes(typeof(SeedDataAttribute), false).Length > 0 ? (u.GetCustomAttributes(typeof(SeedDataAttribute), false)[0] as SeedDataAttribute).Order : 0).ToList();
|
||||
.OrderBy(u => u.GetCustomAttributes(typeof(SeedDataAttribute), false).Length > 0 ? ((SeedDataAttribute)u.GetCustomAttributes(typeof(SeedDataAttribute), false)[0]).Order : 0).ToList();
|
||||
|
||||
foreach (var seedType in seedDataTypes)
|
||||
{
|
||||
@ -378,7 +380,7 @@ public static class SqlSugarSetup
|
||||
.Where(u => !u.GetCustomAttributes<IgnoreTableAttribute>().Any())
|
||||
.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false) &&
|
||||
!u.IsDefined(typeof(SysTableAttribute), false) && !u.IsDefined(typeof(LogTableAttribute), false) && !u.IsDefined(typeof(TenantAttribute), false)).ToList();
|
||||
if (!entityTypes.Any()) return;
|
||||
if (entityTypes.Count == 0) return;
|
||||
|
||||
foreach (var entityType in entityTypes)
|
||||
{
|
||||
@ -392,14 +394,14 @@ public static class SqlSugarSetup
|
||||
// 初始化业务应用种子数据
|
||||
var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))))
|
||||
.Where(u => u.IsDefined(typeof(AppSeedAttribute), false))
|
||||
.OrderBy(u => u.GetCustomAttributes(typeof(SeedDataAttribute), false).Length > 0 ? (u.GetCustomAttributes(typeof(SeedDataAttribute), false)[0] as SeedDataAttribute).Order : 0).ToList();
|
||||
.OrderBy(u => u.GetCustomAttributes(typeof(SeedDataAttribute), false).Length > 0 ? ((SeedDataAttribute)u.GetCustomAttributes(typeof(SeedDataAttribute), false)[0]).Order : 0).ToList();
|
||||
|
||||
foreach (var seedType in seedDataTypes)
|
||||
{
|
||||
var instance = Activator.CreateInstance(seedType);
|
||||
var hasDataMethod = seedType.GetMethod("HasData");
|
||||
var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast<object>().ToList();
|
||||
if (seedData == null) continue;
|
||||
var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast<object>().ToList() ?? new List<object>();
|
||||
if (seedData.Count == 0) continue;
|
||||
|
||||
var entityType = seedType.GetInterfaces().First().GetGenericArguments().First();
|
||||
var entityInfo = db.EntityMaintenance.GetEntityInfo(entityType);
|
||||
@ -409,7 +411,7 @@ public static class SqlSugarSetup
|
||||
{
|
||||
foreach (var sd in seedData)
|
||||
{
|
||||
sd.GetType().GetProperty(nameof(EntityTenantId.TenantId)).SetValue(sd, dbConfigId);
|
||||
sd.GetType().GetProperty(nameof(EntityTenantId.TenantId))!.SetValue(sd, dbConfigId);
|
||||
}
|
||||
}
|
||||
// 若实体包含Pid字段,则设置为当前租户Id
|
||||
@ -417,7 +419,7 @@ public static class SqlSugarSetup
|
||||
{
|
||||
foreach (var sd in seedData)
|
||||
{
|
||||
sd.GetType().GetProperty(nameof(SysOrg.Pid)).SetValue(sd, dbConfigId);
|
||||
sd.GetType().GetProperty(nameof(SysOrg.Pid))!.SetValue(sd, dbConfigId);
|
||||
}
|
||||
}
|
||||
// 若实体包含Id字段,则设置为当前租户Id递增1
|
||||
@ -425,7 +427,7 @@ public static class SqlSugarSetup
|
||||
{
|
||||
foreach (var sd in seedData)
|
||||
{
|
||||
sd.GetType().GetProperty(nameof(EntityBaseId.Id)).SetValue(sd, ++dbConfigId);
|
||||
sd.GetType().GetProperty(nameof(EntityBaseId.Id))!.SetValue(sd, ++dbConfigId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
75
Admin.NET/Admin.NET.Core/Util/BaseFilter.cs
Normal file
75
Admin.NET/Admin.NET.Core/Util/BaseFilter.cs
Normal file
@ -0,0 +1,75 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 模糊查询条件
|
||||
/// </summary>
|
||||
public class Search
|
||||
{
|
||||
/// <summary>
|
||||
/// 字段名称集合
|
||||
/// </summary>
|
||||
public List<string> Fields { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 关键字
|
||||
/// </summary>
|
||||
public string? Keyword { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 筛选过滤条件
|
||||
/// </summary>
|
||||
public class Filter
|
||||
{
|
||||
/// <summary>
|
||||
/// 过滤条件
|
||||
/// </summary>
|
||||
public FilterLogicEnum? Logic { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 筛选过滤条件子项
|
||||
/// </summary>
|
||||
public IEnumerable<Filter>? Filters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 字段名称
|
||||
/// </summary>
|
||||
public string? Field { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 逻辑运算符
|
||||
/// </summary>
|
||||
public FilterOperatorEnum? Operator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 字段值
|
||||
/// </summary>
|
||||
public object? Value { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 过滤条件基类
|
||||
/// </summary>
|
||||
public abstract class BaseFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 模糊查询条件
|
||||
/// </summary>
|
||||
public Search? Search { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模糊查询关键字
|
||||
/// </summary>
|
||||
public string? Keyword { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 筛选过滤条件
|
||||
/// </summary>
|
||||
public Filter? Filter { get; set; }
|
||||
}
|
||||
@ -9,7 +9,7 @@ namespace Admin.NET.Core;
|
||||
/// <summary>
|
||||
/// 全局分页查询输入参数
|
||||
/// </summary>
|
||||
public class BasePageInput
|
||||
public class BasePageInput : BaseFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前页码
|
||||
|
||||
@ -279,6 +279,7 @@ public static class CodeGenUtil
|
||||
var columnList = new List<string>()
|
||||
{
|
||||
nameof(EntityBaseData.CreateOrgId),
|
||||
nameof(EntityBaseData.CreateOrgName),
|
||||
nameof(EntityTenant.TenantId),
|
||||
nameof(EntityBase.CreateTime),
|
||||
nameof(EntityBase.UpdateTime),
|
||||
|
||||
@ -49,12 +49,12 @@ public static class CommonUtil
|
||||
// 代理模式:获取真正的本机地址
|
||||
// X-Original-Host=原始请求
|
||||
// X-Forwarded-Server=从哪里转发过来
|
||||
if (App.HttpContext.Request.Headers.ContainsKey("Origin")) // 配置成完整的路径如(结尾不要带"/"),比如 https://www.abc.com
|
||||
result = $"{App.HttpContext.Request.Headers["Origin"]}";
|
||||
else if (App.HttpContext.Request.Headers.ContainsKey("X-Original")) // 配置成完整的路径如(结尾不要带"/"),比如 https://www.abc.com
|
||||
result = $"{App.HttpContext.Request.Headers["X-Original"]}";
|
||||
else if (App.HttpContext.Request.Headers.ContainsKey("X-Original-Host"))
|
||||
result = $"{App.HttpContext.Request.Scheme}://{App.HttpContext.Request.Headers["X-Original-Host"]}";
|
||||
if (App.HttpContext.Request.Headers.TryGetValue("Origin", out Microsoft.Extensions.Primitives.StringValues value1)) // 配置成完整的路径如(结尾不要带"/"),比如 https://www.abc.com
|
||||
result = $"{value1}";
|
||||
else if (App.HttpContext.Request.Headers.TryGetValue("X-Original", out Microsoft.Extensions.Primitives.StringValues value2)) // 配置成完整的路径如(结尾不要带"/"),比如 https://www.abc.com
|
||||
result = $"{value2}";
|
||||
else if (App.HttpContext.Request.Headers.TryGetValue("X-Original-Host", out Microsoft.Extensions.Primitives.StringValues value3))
|
||||
result = $"{App.HttpContext.Request.Scheme}://{value3}";
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ public static class CommonUtil
|
||||
/// <returns></returns>
|
||||
public static async Task<IActionResult> ExportExcelTemplate<T>(string fileName = null) where T : class, new()
|
||||
{
|
||||
IImporter importer = new ExcelImporter();
|
||||
var importer = new ExcelImporter();
|
||||
var res = await importer.GenerateTemplateBytes<T>();
|
||||
|
||||
return new FileContentResult(res, "application/octet-stream") { FileDownloadName = $"{(string.IsNullOrEmpty(fileName) ? typeof(T).Name : fileName)}.xlsx" };
|
||||
@ -152,9 +152,9 @@ public static class CommonUtil
|
||||
}
|
||||
|
||||
var map = dict.Value.Item1;
|
||||
if (map != null && map.ContainsKey(sourceVal))
|
||||
if (map != null && map.TryGetValue(sourceVal, out string value))
|
||||
{
|
||||
var newVal = map[sourceVal];
|
||||
var newVal = value;
|
||||
targeProp.SetValue(newData, newVal);
|
||||
}
|
||||
else
|
||||
@ -190,7 +190,7 @@ public static class CommonUtil
|
||||
/// <returns></returns>
|
||||
public static async Task<ICollection<T>> ImportExcelData<T>([Required] IFormFile file) where T : class, new()
|
||||
{
|
||||
IImporter importer = new ExcelImporter();
|
||||
var importer = new ExcelImporter();
|
||||
var res = await importer.Import<T>(file.OpenReadStream());
|
||||
var message = string.Empty;
|
||||
if (res.HasError)
|
||||
@ -203,7 +203,46 @@ public static class CommonUtil
|
||||
foreach (var item in drErrorInfo.FieldErrors)
|
||||
message += $"\r\n{item.Key}:{item.Value}(文件第{drErrorInfo.RowIndex}行)";
|
||||
}
|
||||
message += "字段缺失:" + string.Join(",", res.TemplateErrors.Select(m => m.RequireColumnName).ToList());
|
||||
message += "\r\n字段缺失:" + string.Join(",", res.TemplateErrors.Select(m => m.RequireColumnName).ToList());
|
||||
throw Oops.Oh("导入异常:" + message);
|
||||
}
|
||||
return res.Data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导入Excel数据并错误标记
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="file"></param>
|
||||
/// <param name="importResultCallback"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<ICollection<T>> ImportExcelData<T>([Required] IFormFile file, Func<ImportResult<T>, ImportResult<T>> importResultCallback = null) where T : class, new()
|
||||
{
|
||||
var importer = new ExcelImporter();
|
||||
var resultStream = new MemoryStream();
|
||||
var res = await importer.Import<T>(file.OpenReadStream(), resultStream, importResultCallback);
|
||||
resultStream.Seek(0, SeekOrigin.Begin);
|
||||
var userId = App.User?.FindFirst(ClaimConst.UserId)?.Value;
|
||||
|
||||
App.GetRequiredService<SysCacheService>().Remove(CacheConst.KeyExcelTemp + userId);
|
||||
App.GetRequiredService<SysCacheService>().Set(CacheConst.KeyExcelTemp + userId, resultStream, TimeSpan.FromMinutes(5));
|
||||
|
||||
var message = string.Empty;
|
||||
if (res.HasError)
|
||||
{
|
||||
if (res.Exception != null)
|
||||
message += $"\r\n{res.Exception.Message}";
|
||||
foreach (DataRowErrorInfo drErrorInfo in res.RowErrors)
|
||||
{
|
||||
int rowNum = drErrorInfo.RowIndex;
|
||||
foreach (var item in drErrorInfo.FieldErrors)
|
||||
message += $"\r\n{item.Key}:{item.Value}(文件第{drErrorInfo.RowIndex}行)";
|
||||
}
|
||||
if (res.TemplateErrors.Count > 0)
|
||||
message += "\r\n字段缺失:" + string.Join(",", res.TemplateErrors.Select(m => m.RequireColumnName).ToList());
|
||||
|
||||
if (message.Length > 200)
|
||||
message = string.Concat(message.AsSpan(0, 200), "...\r\n异常过多,建议下载错误标记文件查看详细错误信息并重新导入。");
|
||||
throw Oops.Oh("导入异常:" + message);
|
||||
}
|
||||
return res.Data;
|
||||
@ -300,7 +339,7 @@ public static class CommonUtil
|
||||
else
|
||||
{
|
||||
propMappings.Add(propertyInfo.Name, new Tuple<Dictionary<string, object>, PropertyInfo, PropertyInfo>(
|
||||
null, propertyInfo, tTargetProps.ContainsKey(propertyInfo.Name) ? tTargetProps[propertyInfo.Name] : null));
|
||||
null, propertyInfo, tTargetProps.TryGetValue(propertyInfo.Name, out PropertyInfo value) ? value : null));
|
||||
}
|
||||
}
|
||||
|
||||
@ -342,34 +381,34 @@ public static class CommonUtil
|
||||
else
|
||||
{
|
||||
propMappings.Add(propertyInfo.Name, new Tuple<Dictionary<object, string>, PropertyInfo, PropertyInfo>(
|
||||
null, sourceProps.ContainsKey(propertyInfo.Name) ? sourceProps[propertyInfo.Name] : null, propertyInfo));
|
||||
null, sourceProps.TryGetValue(propertyInfo.Name, out PropertyInfo value) ? value : null, propertyInfo));
|
||||
}
|
||||
}
|
||||
|
||||
return propMappings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取属性映射
|
||||
/// </summary>
|
||||
/// <typeparam name="TTarget"></typeparam>
|
||||
/// <returns>整理导入对象的 属性名称, 字典数据,原属性信息,目标属性信息 </returns>
|
||||
private static Dictionary<string, Tuple<string, string>> GetExportDicttMap<TTarget>() where TTarget : new()
|
||||
{
|
||||
// 整理导入对象的属性名称,目标属性名,字典Code
|
||||
var propMappings = new Dictionary<string, Tuple<string, string>>();
|
||||
var tTargetProps = typeof(TTarget).GetProperties();
|
||||
foreach (var propertyInfo in tTargetProps)
|
||||
{
|
||||
var attrs = propertyInfo.GetCustomAttribute<ImportDictAttribute>();
|
||||
if (attrs != null && !string.IsNullOrWhiteSpace(attrs.TypeCode))
|
||||
{
|
||||
propMappings.Add(propertyInfo.Name, new Tuple<string, string>(attrs.TargetPropName, attrs.TypeCode));
|
||||
}
|
||||
}
|
||||
///// <summary>
|
||||
///// 获取属性映射
|
||||
///// </summary>
|
||||
///// <typeparam name="TTarget"></typeparam>
|
||||
///// <returns>整理导入对象的 属性名称, 字典数据,原属性信息,目标属性信息 </returns>
|
||||
//private static Dictionary<string, Tuple<string, string>> GetExportDicttMap<TTarget>() where TTarget : new()
|
||||
//{
|
||||
// // 整理导入对象的属性名称,目标属性名,字典Code
|
||||
// var propMappings = new Dictionary<string, Tuple<string, string>>();
|
||||
// var tTargetProps = typeof(TTarget).GetProperties();
|
||||
// foreach (var propertyInfo in tTargetProps)
|
||||
// {
|
||||
// var attrs = propertyInfo.GetCustomAttribute<ImportDictAttribute>();
|
||||
// if (attrs != null && !string.IsNullOrWhiteSpace(attrs.TypeCode))
|
||||
// {
|
||||
// propMappings.Add(propertyInfo.Name, new Tuple<string, string>(attrs.TargetPropName, attrs.TypeCode));
|
||||
// }
|
||||
// }
|
||||
|
||||
return propMappings;
|
||||
}
|
||||
// return propMappings;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// 解析IP地址
|
||||
|
||||
@ -79,6 +79,7 @@ public class Startup : AppStartup
|
||||
{
|
||||
setting.DateFormatHandling = DateFormatHandling.IsoDateFormat;
|
||||
setting.DateTimeZoneHandling = DateTimeZoneHandling.Local;
|
||||
// setting.Converters.AddDateTimeTypeConverters(localized: true); // 时间本地化
|
||||
setting.DateFormatString = "yyyy-MM-dd HH:mm:ss"; // 时间格式化
|
||||
setting.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; // 忽略循环引用
|
||||
// setting.ContractResolver = new CamelCasePropertyNamesContractResolver(); // 解决动态对象属性名大写
|
||||
@ -135,13 +136,17 @@ public class Startup : AppStartup
|
||||
|
||||
#region Redis消息队列
|
||||
|
||||
//// 替换事件源存储器
|
||||
//options.ReplaceStorer(serviceProvider =>
|
||||
//{
|
||||
// var cacheProvider = serviceProvider.GetRequiredService<NewLife.Caching.ICacheProvider>();
|
||||
// // 创建默认内存通道事件源对象,可自定义队列路由key,如:adminnet
|
||||
// return new RedisEventSourceStorer(cacheProvider, "adminnet", 3000);
|
||||
//});
|
||||
// 替换事件源存储器为Redis
|
||||
var cacheOptions = App.GetConfig<CacheOptions>("Cache", true);
|
||||
if (cacheOptions.CacheType == CacheTypeEnum.Redis.ToString())
|
||||
{
|
||||
options.ReplaceStorer(serviceProvider =>
|
||||
{
|
||||
var cacheProvider = serviceProvider.GetRequiredService<NewLife.Caching.ICacheProvider>();
|
||||
// 创建默认内存通道事件源对象,可自定义队列路由key,如:adminnet_eventsource_queue
|
||||
return new RedisEventSourceStorer(cacheProvider, "adminnet_eventsource_queue", 3000);
|
||||
});
|
||||
}
|
||||
|
||||
#endregion Redis消息队列
|
||||
|
||||
@ -180,7 +185,10 @@ public class Startup : AppStartup
|
||||
//services.AddSingleton<IUserIdProvider, UserIdProvider>();
|
||||
services.AddSignalR(options =>
|
||||
{
|
||||
options.KeepAliveInterval = TimeSpan.FromSeconds(5);
|
||||
options.EnableDetailedErrors = true;
|
||||
options.KeepAliveInterval = TimeSpan.FromSeconds(15); // 服务器端向客户端ping的间隔
|
||||
options.ClientTimeoutInterval = TimeSpan.FromSeconds(30); // 客户端向服务器端ping的间隔
|
||||
options.MaximumReceiveMessageSize = 1024 * 1014 * 10; // 数据包大小10M,默认最大为32K
|
||||
}).AddNewtonsoftJsonProtocol(options => SetNewtonsoftJsonSetting(options.PayloadSerializerSettings));
|
||||
|
||||
// 系统日志
|
||||
|
||||
@ -29,7 +29,7 @@ if (@column.ColumnKey != "True"){
|
||||
/// <summary>
|
||||
/// @(@Model.BusName)分页查询输入参数
|
||||
/// </summary>
|
||||
public class @(@Model.ClassName)Input : BasePageInput
|
||||
public class Page@(@Model.ClassName)Input : BasePageInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 关键字查询
|
||||
|
||||
@ -39,7 +39,7 @@ public class @(@Model.ClassName)Service : IDynamicApiController, ITransient
|
||||
[HttpPost]
|
||||
[ApiDescriptionSettings(Name = "Page")]
|
||||
[DisplayName("分页查询@(@Model.BusName)")]
|
||||
public async Task<SqlSugarPagedList<@(@Model.ClassName)Output>> Page(@(@Model.ClassName)Input input)
|
||||
public async Task<SqlSugarPagedList<@(@Model.ClassName)Output>> Page(Page@(@Model.ClassName)Input input)
|
||||
{
|
||||
@if (haveLikeCdt) {
|
||||
@:input.SearchKey = input.SearchKey?.Trim();
|
||||
@ -84,7 +84,6 @@ if (@column.QueryWhether == "Y"){
|
||||
@:.LeftJoin<@(@column.FkEntityName)>((@(@joinTableName)) => u.@(@column.PropertyName) == @(@column.PropertyName.ToLower()).@(@column.ValueColumn) )
|
||||
}
|
||||
}
|
||||
@:.OrderBy(u => u.CreateTime)
|
||||
@:.Select((@(@joinTableName)) => new @(@Model.ClassName)Output
|
||||
@:{
|
||||
@foreach (var column in Model.TableField){
|
||||
@ -187,7 +186,7 @@ if (@column.ColumnKey == "True"){
|
||||
[HttpGet]
|
||||
[ApiDescriptionSettings(Name = "List")]
|
||||
[DisplayName("获取@(@Model.BusName)列表")]
|
||||
public async Task<List<@(@Model.ClassName)Output>> List([FromQuery] @(@Model.ClassName)Input input)
|
||||
public async Task<List<@(@Model.ClassName)Output>> List([FromQuery] Page@(@Model.ClassName)Input input)
|
||||
{
|
||||
return await _@(@Model.LowerClassName)Rep.AsQueryable().Select<@(@Model.ClassName)Output>().ToListAsync();
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@
|
||||
@:<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
@:<el-form-item label="@column.ColumnComment" prop="@(@column.LowerPropertyName)">
|
||||
@:<el-select clearable v-model="state.ruleForm.@(@column.LowerPropertyName)" placeholder="请选择@(@column.ColumnComment)">
|
||||
@:<el-option v-for="(item,index) in dl('@(@column.DictTypeCode)')" :key="index" :value="@(@column.NetType.StartsWith("string") ? "item.code" : "Number(item.value)")" :label="`[${item.code}] ${item.value}`"></el-option>
|
||||
@:<el-option v-for="(item,index) in dl('@(@column.DictTypeCode)')" :key="index" :value="@(@column.NetType.StartsWith("string") ? "item.code" : "Number(item.value)")" :label="`${item.name} [${item.code}] ${item.value}`"></el-option>
|
||||
@:
|
||||
</el-select>
|
||||
@:
|
||||
|
||||
@ -18,31 +18,31 @@
|
||||
}
|
||||
}
|
||||
<template>
|
||||
<div class="@(@Model.LowerClassName)-container" v-loading="options.loading">
|
||||
<div class="@(@Model.LowerClassName)-container">
|
||||
<el-card shadow="hover" :body-style="{ padding: '20px 20px 16px 10px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
|
||||
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" label-width="auto" style="flex: 1 1 0%" @@submit.prevent="handleQuery" >
|
||||
<el-row :gutter="10">
|
||||
@if(Model.QueryWhetherList.Count > 0){
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb5">
|
||||
<el-form-item label="关键字" prop="searchKey">
|
||||
<el-input v-model="state.queryParams.searchKey" placeholder="请输入模糊查询关键字" clearable @@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
foreach (var column in Model.QueryWhetherList) {
|
||||
if(@column.EffectType == "Input" || @column.EffectType == "InputTextArea") {
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.showAdvanceQueryUI">
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb5" v-if="state.showAdvanceQueryUI">
|
||||
<el-form-item label="@column.ColumnComment" prop="@(@column.LowerPropertyName)">
|
||||
<el-input v-model="state.queryParams.@(@column.LowerPropertyName)" placeholder="@column.ColumnComment" clearable @@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
} else if(@column.EffectType == "InputNumber") {
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.showAdvanceQueryUI">
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb5" v-if="state.showAdvanceQueryUI">
|
||||
<el-form-item label="@column.ColumnComment">
|
||||
<el-input-number v-model="state.queryParams.@(@column.LowerPropertyName)" placeholder="请输入@(@column.ColumnComment)" clearable @@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
} else if(@column.EffectType == "fk") {
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.showAdvanceQueryUI">
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb5" v-if="state.showAdvanceQueryUI">
|
||||
<el-form-item label="@column.ColumnComment">
|
||||
<el-select filterable="" v-model="state.queryParams.@(@column.LowerPropertyName)" placeholder="请选择@(@column.ColumnComment)" clearable>
|
||||
<el-option v-for="(item,index) in @LowerFirstLetter(@column.FkEntityName)@(@column.PropertyName)DropdownList" :key="index" :value="item.value" :label="item.label" />
|
||||
@ -50,15 +50,15 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
} else if(@column.EffectType == "Select") {
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.showAdvanceQueryUI">
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb5" v-if="state.showAdvanceQueryUI">
|
||||
<el-form-item label="@column.ColumnComment" prop="@(@column.LowerPropertyName)">
|
||||
<el-select v-model="state.queryParams.@(@column.LowerPropertyName)" filterable placeholder="请选择@(@column.ColumnComment)" clearable @@keyup.enter.native="handleQuery" >
|
||||
<el-option v-for="(item,index) in dl('@(@column.DictTypeCode)')" :key="index" :value="item.code" :label="`${item.name} [${item.code}] ${item.value}`" />
|
||||
<el-option v-for="(item,index) in dl('@(@column.DictTypeCode)')" :key="index" :value="item.value" :label="`${item.name} [${item.code}] ${item.value}`" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
} else if(@column.EffectType == "EnumSelector") {
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.showAdvanceQueryUI">
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb5" v-if="state.showAdvanceQueryUI">
|
||||
<el-form-item label="@column.ColumnComment" prop="@(@column.LowerPropertyName)">
|
||||
<el-select v-model="state.queryParams.@(@column.LowerPropertyName)" filterable placeholder="请选择@(@column.ColumnComment)" clearable @@keyup.enter.native="handleQuery" >
|
||||
<el-option v-for="(item,index) in dl('@(@column.DictTypeCode)')" :key="index" :value="item.value" :label="`${item.name} [${item.code}] ${item.value}`" />
|
||||
@ -66,7 +66,7 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
} else if(@column.EffectType == "DatePicker") {
|
||||
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.showAdvanceQueryUI">
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb5" v-if="state.showAdvanceQueryUI">
|
||||
<el-form-item label="@column.ColumnComment" prop="@(@column.LowerPropertyName)">
|
||||
@if(@column.QueryType == "~"){
|
||||
@:<el-date-picker type="daterange" v-model="state.queryParams.@(@column.LowerPropertyName)Range" value-format="YYYY-MM-DD HH:mm:ss" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" />
|
||||
@ -154,11 +154,7 @@
|
||||
@:<template #row_@(@column.LowerPropertyName)="{ row }">
|
||||
@:<el-tag :type="dv('@(@column.DictTypeCode)', row.@(@column.LowerPropertyName))?.tagType"> {{dv('@(@column.DictTypeCode)', row.@column.LowerPropertyName)?.name}}</el-tag>
|
||||
@:</template>
|
||||
} else if(@column.EffectType == "DatePicker") {
|
||||
@:<template #row_@(@column.LowerPropertyName)="{ row }">
|
||||
@:<span>{{ formatDate(new Date(row.@(@column.LowerPropertyName)), 'YYYY-mm-dd HH:MM:SS') }}</span>
|
||||
@:</template>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
<template #row_record="{ row }">
|
||||
@ -167,14 +163,14 @@
|
||||
<template #row_buttons="{ row }">
|
||||
@if(@Model.PrintType == "custom") {
|
||||
<el-tooltip content="打印" placement="top">
|
||||
<el-button icon="ele-Printer" size="small" text type="primary" @@click="handlePrint(row)" v-auth="'@(@Model.LowerClassName):print'" :disabled="row.status === 1" />
|
||||
<el-button icon="ele-Printer" size="small" text type="primary" @@click="handlePrint(row)" v-auth="'@(@Model.LowerClassName):print'" />
|
||||
</el-tooltip>
|
||||
}
|
||||
<el-tooltip content="编辑" placement="top">
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @@click="handleEdit(row)" v-auth="'@(@Model.LowerClassName):update'" :disabled="row.status === 1" />
|
||||
<el-button icon="ele-Edit" size="small" text type="primary" @@click="handleEdit(row)" v-auth="'@(@Model.LowerClassName):update'" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @@click="handleDelete(row)" v-auth="'@(@Model.LowerClassName):delete'" :disabled="row.status === 1" />
|
||||
<el-button icon="ele-Delete" size="small" text type="danger" @@click="handleDelete(row)" v-auth="'@(@Model.LowerClassName):delete'" />
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
@ -198,7 +194,7 @@ import { Local } from '/@@/utils/storage';
|
||||
@:import { codeToName, getConstType } from "/@@/utils/constHelper";
|
||||
}
|
||||
@if(@Model.TableField.Any(x=>x.EffectType == "Select") || @Model.TableField.Any(x=>x.EffectType == "EnumSelector")){
|
||||
@:import { getDictDataItem as di, getDictDataList as dl } from '/@@/utils/dict-utils';
|
||||
@:import { getDictLabelByVal as di, getDictDataList as dl } from '/@@/utils/dict-utils';
|
||||
}
|
||||
@if(@Model.TableField.Any(x=>x.EffectType == "EnumSelector")){
|
||||
@:import { getDictLabelByVal as dv } from '/@@/utils/dict-utils';
|
||||
@ -296,13 +292,13 @@ const options = useVxeTable<@(@Model.ClassName)>(
|
||||
} else if(@column.EffectType == "EnumSelector") {
|
||||
@:{ field: '@column.LowerPropertyName', title: '@column.ColumnComment', minWidth: 100, showOverflow: 'tooltip', slots: { default: 'row_@column.LowerPropertyName' }, @whethersortable },
|
||||
} else if(@column.EffectType == "DatePicker") {
|
||||
@:{ field: '@column.LowerPropertyName', title: '@column.ColumnComment', minWidth: 100, showOverflow: 'tooltip', slots: { default: 'row_@column.LowerPropertyName' }, @whethersortable },
|
||||
@:{ field: '@column.LowerPropertyName', title: '@column.ColumnComment', minWidth: 100, showOverflow: 'tooltip', formatter: ({ cellValue }) => formatDate(new Date(cellValue), 'YYYY-mm-dd HH:MM:SS'), @whethersortable },
|
||||
} else {
|
||||
@:{ field: '@column.LowerPropertyName', title: '@column.ColumnComment', minWidth: 100, showOverflow: 'tooltip', @whethersortable},
|
||||
}
|
||||
}
|
||||
}
|
||||
{ field: '', title: '修改记录', width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } },
|
||||
{ title: '修改记录', width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } },
|
||||
{ title: '操作', fixed: 'right', width: 180, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||
],
|
||||
},
|
||||
@ -317,7 +313,7 @@ const options = useVxeTable<@(@Model.ClassName)>(
|
||||
// 工具栏配置
|
||||
toolbarConfig: { export: false },
|
||||
// 行设置
|
||||
rowConfig: { height: 80 },
|
||||
// rowConfig: { height: 80 },
|
||||
}
|
||||
);
|
||||
|
||||
@ -338,11 +334,13 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
|
||||
|
||||
// 查询操作
|
||||
const handleQuery = async (reset = false) => {
|
||||
options.loading = true;
|
||||
await xGrid.value?.commitProxy('query');
|
||||
options.loading = false;
|
||||
};
|
||||
|
||||
// 重置操作
|
||||
const resetQuery = () => {
|
||||
const resetQuery = async () => {
|
||||
state.queryParams.searchKey = undefined,
|
||||
@if(Model.QueryWhetherList.Count > 0) {
|
||||
@foreach (var column in Model.QueryWhetherList) {
|
||||
@ -398,7 +396,7 @@ const handleDelete = (row: any) => {
|
||||
} else {
|
||||
@:await delete@(@Model.ClassName)(row);
|
||||
}
|
||||
handleQuery();
|
||||
await handleQuery();
|
||||
ElMessage.success('删除成功');
|
||||
})
|
||||
.catch(() => {});
|
||||
|
||||
@ -36,10 +36,12 @@ public class DingTalkConst
|
||||
/// 主部门Id
|
||||
/// </summary>
|
||||
public const string DeptId = "sys00-mainDeptId";
|
||||
|
||||
/// <summary>
|
||||
/// 主部门
|
||||
/// </summary>
|
||||
public const string Dept = "sys00-mainDept";
|
||||
|
||||
/// <summary>
|
||||
/// 职位
|
||||
/// </summary>
|
||||
|
||||
@ -73,23 +73,25 @@ public class DingTalkUser : EntityBase
|
||||
[SugarColumn(ColumnDescription = "工号", Length = 16)]
|
||||
[MaxLength(16)]
|
||||
public string? JobNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 主部门Id
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "主部门Id", Length = 16)]
|
||||
[MaxLength(16)]
|
||||
public string? DeptId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 主部门
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "主部门", Length = 16)]
|
||||
[MaxLength(16)]
|
||||
public string? Dept { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 职位
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "职位", Length = 16)]
|
||||
[MaxLength(16)]
|
||||
public string? Position { get; set; }
|
||||
|
||||
}
|
||||
@ -43,7 +43,7 @@ public class DingTalkService : IDynamicApiController, IScoped
|
||||
/// <param name="access_token"></param>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[DisplayName("获取在职员工列表")]
|
||||
[HttpPost, DisplayName("获取在职员工列表")]
|
||||
public async Task<DingTalkBaseResponse<GetDingTalkCurrentEmployeesListOutput>> GetDingTalkCurrentEmployeesList(string access_token, [Required] GetDingTalkCurrentEmployeesListInput input)
|
||||
{
|
||||
return await _dingTalkApi.GetDingTalkCurrentEmployeesList(access_token, input);
|
||||
@ -55,7 +55,7 @@ public class DingTalkService : IDynamicApiController, IScoped
|
||||
/// <param name="access_token"></param>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[DisplayName("获取员工花名册字段信息")]
|
||||
[HttpPost, DisplayName("获取员工花名册字段信息")]
|
||||
public async Task<DingTalkBaseResponse<List<DingTalkEmpRosterFieldVo>>> GetDingTalkCurrentEmployeesRosterList(string access_token, [Required] GetDingTalkCurrentEmployeesRosterListInput input)
|
||||
{
|
||||
return await _dingTalkApi.GetDingTalkCurrentEmployeesRosterList(access_token, input);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
@ -10,6 +10,7 @@ namespace Admin.NET.Plugin.GoView;
|
||||
/// GoView 项目表
|
||||
/// </summary>
|
||||
[SugarTable(null, "GoView 项目表")]
|
||||
[SysTable]
|
||||
public class GoViewPro : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@ -10,6 +10,7 @@ namespace Admin.NET.Plugin.GoView;
|
||||
/// GoView 项目数据表
|
||||
/// </summary>
|
||||
[SugarTable(null, "GoView 项目数据表")]
|
||||
[SysTable]
|
||||
public class GoViewProData : EntityTenant
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@ -34,7 +34,7 @@ public class GoViewSysService : IDynamicApiController
|
||||
[DisplayName("GoView 登录")]
|
||||
public async Task<GoViewLoginOutput> Login(GoViewLoginInput input)
|
||||
{
|
||||
_sysCacheService.Set($"{CacheConst.KeyConfig}{CommonConst.SysCaptcha}", false);
|
||||
_sysCacheService.Set($"{CacheConst.KeyConfig}{ConfigConst.SysCaptcha}", false);
|
||||
|
||||
input.Password = CryptogramUtil.SM2Encrypt(input.Password);
|
||||
var loginResult = await _sysAuthService.Login(new LoginInput()
|
||||
@ -43,7 +43,7 @@ public class GoViewSysService : IDynamicApiController
|
||||
Password = input.Password,
|
||||
});
|
||||
|
||||
_sysCacheService.Remove($"{CacheConst.KeyConfig}{CommonConst.SysCaptcha}");
|
||||
_sysCacheService.Remove($"{CacheConst.KeyConfig}{ConfigConst.SysCaptcha}");
|
||||
|
||||
var sysUser = await _sysUserRep.AsQueryable().ClearFilter().FirstAsync(u => u.Account.Equals(input.Username));
|
||||
return new GoViewLoginOutput()
|
||||
|
||||
@ -2,13 +2,13 @@
|
||||
"name": "admin.net.pro",
|
||||
"type": "module",
|
||||
"version": "2.4.33",
|
||||
"lastBuildTime": "2024.07.12",
|
||||
"lastBuildTime": "2024.07.20",
|
||||
"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",
|
||||
"author": "zuohuaijun",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"build": "node --max-old-space-size=8192 ./node_modules/vite/bin/vite build",
|
||||
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/",
|
||||
"build-api": "cd api_build/ && build.bat"
|
||||
},
|
||||
@ -18,7 +18,7 @@
|
||||
"@logicflow/extension": "^1.2.27",
|
||||
"@microsoft/signalr": "^8.0.7",
|
||||
"@vue-office/docx": "^1.6.2",
|
||||
"@vue-office/excel": "^1.7.8",
|
||||
"@vue-office/excel": "^1.7.11",
|
||||
"@vue-office/pdf": "^2.0.2",
|
||||
"@vueuse/core": "^10.11.0",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
@ -31,7 +31,7 @@
|
||||
"echarts": "^5.5.1",
|
||||
"echarts-gl": "^2.0.9",
|
||||
"echarts-wordcloud": "^2.1.0",
|
||||
"element-plus": "^2.7.6",
|
||||
"element-plus": "^2.7.7",
|
||||
"exceljs": "^4.4.0",
|
||||
"ezuikit": "^1.0.0",
|
||||
"ezuikit-js": "^8.0.5",
|
||||
@ -57,7 +57,7 @@
|
||||
"splitpanes": "^3.1.5",
|
||||
"vcrontab-3": "^3.3.22",
|
||||
"vform3-builds": "^3.0.10",
|
||||
"vue": "^3.4.31",
|
||||
"vue": "^3.4.33",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-demi": "^0.14.8",
|
||||
"vue-grid-layout": "3.0.0-beta1",
|
||||
@ -68,8 +68,8 @@
|
||||
"vue-signature-pad": "^3.0.2",
|
||||
"vue3-tree-org": "^4.2.2",
|
||||
"vuedraggable": "4.0.3",
|
||||
"vxe-pc-ui": "^4.0.61",
|
||||
"vxe-table": "^4.7.48",
|
||||
"vxe-pc-ui": "^4.0.77",
|
||||
"vxe-table": "^4.7.56",
|
||||
"vxe-table-plugin-element": "^4.0.4",
|
||||
"vxe-table-plugin-export-xlsx": "^4.0.5",
|
||||
"xe-utils": "^3.5.28",
|
||||
@ -79,24 +79,24 @@
|
||||
"@iconify/vue": "^4.1.2",
|
||||
"@plugin-web-update-notification/vite": "^1.7.1",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^20.14.10",
|
||||
"@types/node": "^20.14.11",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/sortablejs": "^1.15.8",
|
||||
"@typescript-eslint/eslint-plugin": "^7.16.0",
|
||||
"@typescript-eslint/parser": "^7.16.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.16.1",
|
||||
"@typescript-eslint/parser": "^7.16.1",
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"@vitejs/plugin-vue-jsx": "^4.0.0",
|
||||
"@vue/compiler-sfc": "^3.4.31",
|
||||
"@vue/compiler-sfc": "^3.4.33",
|
||||
"code-inspector-plugin": "^0.14.2",
|
||||
"eslint": "^9.6.0",
|
||||
"eslint": "^9.7.0",
|
||||
"eslint-plugin-vue": "^9.27.0",
|
||||
"less": "^4.2.0",
|
||||
"prettier": "^3.3.2",
|
||||
"prettier": "^3.3.3",
|
||||
"rollup-plugin-visualizer": "^5.12.0",
|
||||
"sass": "^1.77.7",
|
||||
"terser": "^5.31.2",
|
||||
"sass": "^1.77.8",
|
||||
"terser": "^5.31.3",
|
||||
"typescript": "^5.5.3",
|
||||
"vite": "^5.3.3",
|
||||
"vite": "^5.3.4",
|
||||
"vite-plugin-cdn-import": "^1.0.1",
|
||||
"vite-plugin-compression2": "^1.1.2",
|
||||
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||
|
||||
@ -159,6 +159,12 @@ const updateFavicon = (url: string): void => {
|
||||
|
||||
// 加载系统信息
|
||||
loadSysInfo();
|
||||
|
||||
// 阻止火狐浏览器在拖动时打开新窗口
|
||||
document.body.ondrop = function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@ -45,6 +45,7 @@ export * from './apis/sys-print-api';
|
||||
export * from './apis/sys-proc-api';
|
||||
export * from './apis/sys-region-api';
|
||||
export * from './apis/sys-role-api';
|
||||
export * from './apis/sys-schedule-api';
|
||||
export * from './apis/sys-server-api';
|
||||
export * from './apis/sys-sms-api';
|
||||
export * from './apis/sys-tenant-api';
|
||||
|
||||
@ -501,49 +501,6 @@ export const SysAuthApiAxiosParamCreator = function (configuration?: Configurati
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
|
||||
return {
|
||||
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取水印配置 🔖
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
apiSysAuthWatermarkConfigGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/api/sysAuth/watermarkConfig`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication Bearer required
|
||||
// http bearer authentication required
|
||||
if (configuration && configuration.accessToken) {
|
||||
const accessToken = typeof configuration.accessToken === 'function'
|
||||
? await configuration.accessToken()
|
||||
: await configuration.accessToken;
|
||||
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
|
||||
}
|
||||
|
||||
const query = new URLSearchParams(localVarUrlObj.search);
|
||||
for (const key in localVarQueryParameter) {
|
||||
query.set(key, localVarQueryParameter[key]);
|
||||
}
|
||||
for (const key in options.params) {
|
||||
query.set(key, options.params[key]);
|
||||
}
|
||||
localVarUrlObj.search = (new URLSearchParams(query)).toString();
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
|
||||
return {
|
||||
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
|
||||
options: localVarRequestOptions,
|
||||
@ -694,19 +651,6 @@ export const SysAuthApiFp = function(configuration?: Configuration) {
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取水印配置 🔖
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysAuthWatermarkConfigGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
|
||||
const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).apiSysAuthWatermarkConfigGet(options);
|
||||
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
|
||||
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@ -812,15 +756,6 @@ export const SysAuthApiFactory = function (configuration?: Configuration, basePa
|
||||
async apiSysAuthUserInfoGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultLoginUserOutput>> {
|
||||
return SysAuthApiFp(configuration).apiSysAuthUserInfoGet(options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取水印配置 🔖
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysAuthWatermarkConfigGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
|
||||
return SysAuthApiFp(configuration).apiSysAuthWatermarkConfigGet(options).then((request) => request(axios, basePath));
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@ -937,14 +872,4 @@ export class SysAuthApi extends BaseAPI {
|
||||
public async apiSysAuthUserInfoGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultLoginUserOutput>> {
|
||||
return SysAuthApiFp(this.configuration).apiSysAuthUserInfoGet(options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @summary 获取水印配置 🔖
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof SysAuthApi
|
||||
*/
|
||||
public async apiSysAuthWatermarkConfigGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
|
||||
return SysAuthApiFp(this.configuration).apiSysAuthWatermarkConfigGet(options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ import { Configuration } from '../configuration';
|
||||
// Some imports not used depending on template conditions
|
||||
// @ts-ignore
|
||||
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
|
||||
import { AdminResultIActionResult } from '../models';
|
||||
import { AdminResultListApiOutput } from '../models';
|
||||
import { AdminResultSmKeyPairOutput } from '../models';
|
||||
import { AdminResultString } from '../models';
|
||||
@ -74,6 +75,54 @@ export const SysCommonApiAxiosParamCreator = function (configuration?: Configura
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 下载标记错误的临时 Excel(全局) 🔖
|
||||
* @param {string} [fileName]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
apiSysCommonDownloadErrorExcelTempPost: async (fileName?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/api/sysCommon/downloadErrorExcelTemp`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication Bearer required
|
||||
// http bearer authentication required
|
||||
if (configuration && configuration.accessToken) {
|
||||
const accessToken = typeof configuration.accessToken === 'function'
|
||||
? await configuration.accessToken()
|
||||
: await configuration.accessToken;
|
||||
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
|
||||
}
|
||||
|
||||
if (fileName !== undefined) {
|
||||
localVarQueryParameter['fileName'] = fileName;
|
||||
}
|
||||
|
||||
const query = new URLSearchParams(localVarUrlObj.search);
|
||||
for (const key in localVarQueryParameter) {
|
||||
query.set(key, localVarQueryParameter[key]);
|
||||
}
|
||||
for (const key in options.params) {
|
||||
query.set(key, options.params[key]);
|
||||
}
|
||||
localVarUrlObj.search = (new URLSearchParams(query)).toString();
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
|
||||
return {
|
||||
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取MD5加密字符串 🏆
|
||||
@ -129,6 +178,49 @@ export const SysCommonApiAxiosParamCreator = function (configuration?: Configura
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取机器序列号 🔖
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
apiSysCommonMachineSerialKeyGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/api/sysCommon/machineSerialKey`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication Bearer required
|
||||
// http bearer authentication required
|
||||
if (configuration && configuration.accessToken) {
|
||||
const accessToken = typeof configuration.accessToken === 'function'
|
||||
? await configuration.accessToken()
|
||||
: await configuration.accessToken;
|
||||
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
|
||||
}
|
||||
|
||||
const query = new URLSearchParams(localVarUrlObj.search);
|
||||
for (const key in localVarQueryParameter) {
|
||||
query.set(key, localVarQueryParameter[key]);
|
||||
}
|
||||
for (const key in options.params) {
|
||||
query.set(key, options.params[key]);
|
||||
}
|
||||
localVarUrlObj.search = (new URLSearchParams(query)).toString();
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
|
||||
return {
|
||||
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取国密公钥私钥对 🏆
|
||||
@ -195,6 +287,20 @@ export const SysCommonApiFp = function(configuration?: Configuration) {
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 下载标记错误的临时 Excel(全局) 🔖
|
||||
* @param {string} [fileName]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysCommonDownloadErrorExcelTempPost(fileName?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultIActionResult>>> {
|
||||
const localVarAxiosArgs = await SysCommonApiAxiosParamCreator(configuration).apiSysCommonDownloadErrorExcelTempPost(fileName, options);
|
||||
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
|
||||
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取MD5加密字符串 🏆
|
||||
@ -210,6 +316,19 @@ export const SysCommonApiFp = function(configuration?: Configuration) {
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取机器序列号 🔖
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysCommonMachineSerialKeyGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultString>>> {
|
||||
const localVarAxiosArgs = await SysCommonApiAxiosParamCreator(configuration).apiSysCommonMachineSerialKeyGet(options);
|
||||
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
|
||||
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取国密公钥私钥对 🏆
|
||||
@ -242,6 +361,16 @@ export const SysCommonApiFactory = function (configuration?: Configuration, base
|
||||
async apiSysCommonApiListGet(groupName?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListApiOutput>> {
|
||||
return SysCommonApiFp(configuration).apiSysCommonApiListGet(groupName, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 下载标记错误的临时 Excel(全局) 🔖
|
||||
* @param {string} [fileName]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysCommonDownloadErrorExcelTempPost(fileName?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultIActionResult>> {
|
||||
return SysCommonApiFp(configuration).apiSysCommonDownloadErrorExcelTempPost(fileName, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取MD5加密字符串 🏆
|
||||
@ -253,6 +382,15 @@ export const SysCommonApiFactory = function (configuration?: Configuration, base
|
||||
async apiSysCommonMD5EncryptTextUppercaseGet(text: string, uppercase: boolean, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultString>> {
|
||||
return SysCommonApiFp(configuration).apiSysCommonMD5EncryptTextUppercaseGet(text, uppercase, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取机器序列号 🔖
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysCommonMachineSerialKeyGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultString>> {
|
||||
return SysCommonApiFp(configuration).apiSysCommonMachineSerialKeyGet(options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取国密公钥私钥对 🏆
|
||||
@ -283,6 +421,17 @@ export class SysCommonApi extends BaseAPI {
|
||||
public async apiSysCommonApiListGet(groupName?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListApiOutput>> {
|
||||
return SysCommonApiFp(this.configuration).apiSysCommonApiListGet(groupName, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @summary 下载标记错误的临时 Excel(全局) 🔖
|
||||
* @param {string} [fileName]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof SysCommonApi
|
||||
*/
|
||||
public async apiSysCommonDownloadErrorExcelTempPost(fileName?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultIActionResult>> {
|
||||
return SysCommonApiFp(this.configuration).apiSysCommonDownloadErrorExcelTempPost(fileName, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @summary 获取MD5加密字符串 🏆
|
||||
@ -295,6 +444,16 @@ export class SysCommonApi extends BaseAPI {
|
||||
public async apiSysCommonMD5EncryptTextUppercaseGet(text: string, uppercase: boolean, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultString>> {
|
||||
return SysCommonApiFp(this.configuration).apiSysCommonMD5EncryptTextUppercaseGet(text, uppercase, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @summary 获取机器序列号 🔖
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof SysCommonApi
|
||||
*/
|
||||
public async apiSysCommonMachineSerialKeyGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultString>> {
|
||||
return SysCommonApiFp(this.configuration).apiSysCommonMachineSerialKeyGet(options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @summary 获取国密公钥私钥对 🏆
|
||||
|
||||
@ -22,6 +22,9 @@ import { AdminResultListSysNotice } from '../models';
|
||||
import { AdminResultSqlSugarPagedListSysNotice } from '../models';
|
||||
import { AdminResultSqlSugarPagedListSysNoticeUser } from '../models';
|
||||
import { DeleteNoticeInput } from '../models';
|
||||
import { Filter } from '../models';
|
||||
import { FilterLogicEnum } from '../models';
|
||||
import { FilterOperatorEnum } from '../models';
|
||||
import { NoticeInput } from '../models';
|
||||
import { NoticeTypeEnum } from '../models';
|
||||
import { PageNoticeInput } from '../models';
|
||||
@ -186,10 +189,18 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura
|
||||
* @param {string} [field] 排序字段
|
||||
* @param {string} [order] 排序方向
|
||||
* @param {string} [descStr] 降序排序
|
||||
* @param {Array<string>} [searchFields] 字段名称集合
|
||||
* @param {string} [searchKeyword] 关键字
|
||||
* @param {string} [keyword] 模糊查询关键字
|
||||
* @param {FilterLogicEnum} [filterLogic] 过滤条件
|
||||
* @param {Array<Filter>} [filterFilters] 筛选过滤条件子项
|
||||
* @param {string} [filterField] 字段名称
|
||||
* @param {FilterOperatorEnum} [filterOperator] 逻辑运算符
|
||||
* @param {any} [filterValue] 字段值
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
apiSysNoticePageReceivedGet: async (title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
apiSysNoticePageReceivedGet: async (title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, searchFields?: Array<string>, searchKeyword?: string, keyword?: string, filterLogic?: FilterLogicEnum, filterFilters?: Array<Filter>, filterField?: string, filterOperator?: FilterOperatorEnum, filterValue?: any, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/api/sysNotice/pageReceived`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
|
||||
@ -238,6 +249,38 @@ export const SysNoticeApiAxiosParamCreator = function (configuration?: Configura
|
||||
localVarQueryParameter['DescStr'] = descStr;
|
||||
}
|
||||
|
||||
if (searchFields) {
|
||||
localVarQueryParameter['Search.Fields'] = searchFields;
|
||||
}
|
||||
|
||||
if (searchKeyword !== undefined) {
|
||||
localVarQueryParameter['Search.Keyword'] = searchKeyword;
|
||||
}
|
||||
|
||||
if (keyword !== undefined) {
|
||||
localVarQueryParameter['Keyword'] = keyword;
|
||||
}
|
||||
|
||||
if (filterLogic !== undefined) {
|
||||
localVarQueryParameter['Filter.Logic'] = filterLogic;
|
||||
}
|
||||
|
||||
if (filterFilters) {
|
||||
localVarQueryParameter['Filter.Filters'] = filterFilters;
|
||||
}
|
||||
|
||||
if (filterField !== undefined) {
|
||||
localVarQueryParameter['Filter.Field'] = filterField;
|
||||
}
|
||||
|
||||
if (filterOperator !== undefined) {
|
||||
localVarQueryParameter['Filter.Operator'] = filterOperator;
|
||||
}
|
||||
|
||||
if (filterValue !== undefined) {
|
||||
localVarQueryParameter['Filter.Value'] = filterValue;
|
||||
}
|
||||
|
||||
const query = new URLSearchParams(localVarUrlObj.search);
|
||||
for (const key in localVarQueryParameter) {
|
||||
query.set(key, localVarQueryParameter[key]);
|
||||
@ -502,11 +545,19 @@ export const SysNoticeApiFp = function(configuration?: Configuration) {
|
||||
* @param {string} [field] 排序字段
|
||||
* @param {string} [order] 排序方向
|
||||
* @param {string} [descStr] 降序排序
|
||||
* @param {Array<string>} [searchFields] 字段名称集合
|
||||
* @param {string} [searchKeyword] 关键字
|
||||
* @param {string} [keyword] 模糊查询关键字
|
||||
* @param {FilterLogicEnum} [filterLogic] 过滤条件
|
||||
* @param {Array<Filter>} [filterFilters] 筛选过滤条件子项
|
||||
* @param {string} [filterField] 字段名称
|
||||
* @param {FilterOperatorEnum} [filterOperator] 逻辑运算符
|
||||
* @param {any} [filterValue] 字段值
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSqlSugarPagedListSysNoticeUser>>> {
|
||||
const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).apiSysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, options);
|
||||
async apiSysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, searchFields?: Array<string>, searchKeyword?: string, keyword?: string, filterLogic?: FilterLogicEnum, filterFilters?: Array<Filter>, filterField?: string, filterOperator?: FilterOperatorEnum, filterValue?: any, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSqlSugarPagedListSysNoticeUser>>> {
|
||||
const localVarAxiosArgs = await SysNoticeApiAxiosParamCreator(configuration).apiSysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, searchFields, searchKeyword, keyword, filterLogic, filterFilters, filterField, filterOperator, filterValue, options);
|
||||
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
|
||||
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
|
||||
return axios.request(axiosRequestArgs);
|
||||
@ -616,11 +667,19 @@ export const SysNoticeApiFactory = function (configuration?: Configuration, base
|
||||
* @param {string} [field] 排序字段
|
||||
* @param {string} [order] 排序方向
|
||||
* @param {string} [descStr] 降序排序
|
||||
* @param {Array<string>} [searchFields] 字段名称集合
|
||||
* @param {string} [searchKeyword] 关键字
|
||||
* @param {string} [keyword] 模糊查询关键字
|
||||
* @param {FilterLogicEnum} [filterLogic] 过滤条件
|
||||
* @param {Array<Filter>} [filterFilters] 筛选过滤条件子项
|
||||
* @param {string} [filterField] 字段名称
|
||||
* @param {FilterOperatorEnum} [filterOperator] 逻辑运算符
|
||||
* @param {any} [filterValue] 字段值
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSqlSugarPagedListSysNoticeUser>> {
|
||||
return SysNoticeApiFp(configuration).apiSysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, options).then((request) => request(axios, basePath));
|
||||
async apiSysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, searchFields?: Array<string>, searchKeyword?: string, keyword?: string, filterLogic?: FilterLogicEnum, filterFilters?: Array<Filter>, filterField?: string, filterOperator?: FilterOperatorEnum, filterValue?: any, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSqlSugarPagedListSysNoticeUser>> {
|
||||
return SysNoticeApiFp(configuration).apiSysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, searchFields, searchKeyword, keyword, filterLogic, filterFilters, filterField, filterOperator, filterValue, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
@ -714,12 +773,20 @@ export class SysNoticeApi extends BaseAPI {
|
||||
* @param {string} [field] 排序字段
|
||||
* @param {string} [order] 排序方向
|
||||
* @param {string} [descStr] 降序排序
|
||||
* @param {Array<string>} [searchFields] 字段名称集合
|
||||
* @param {string} [searchKeyword] 关键字
|
||||
* @param {string} [keyword] 模糊查询关键字
|
||||
* @param {FilterLogicEnum} [filterLogic] 过滤条件
|
||||
* @param {Array<Filter>} [filterFilters] 筛选过滤条件子项
|
||||
* @param {string} [filterField] 字段名称
|
||||
* @param {FilterOperatorEnum} [filterOperator] 逻辑运算符
|
||||
* @param {any} [filterValue] 字段值
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof SysNoticeApi
|
||||
*/
|
||||
public async apiSysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSqlSugarPagedListSysNoticeUser>> {
|
||||
return SysNoticeApiFp(this.configuration).apiSysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, options).then((request) => request(this.axios, this.basePath));
|
||||
public async apiSysNoticePageReceivedGet(title?: string, type?: NoticeTypeEnum, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, searchFields?: Array<string>, searchKeyword?: string, keyword?: string, filterLogic?: FilterLogicEnum, filterFilters?: Array<Filter>, filterField?: string, filterOperator?: FilterOperatorEnum, filterValue?: any, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSqlSugarPagedListSysNoticeUser>> {
|
||||
return SysNoticeApiFp(this.configuration).apiSysNoticePageReceivedGet(title, type, page, pageSize, field, order, descStr, searchFields, searchKeyword, keyword, filterLogic, filterFilters, filterField, filterOperator, filterValue, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
/**
|
||||
*
|
||||
|
||||
561
Web/src/api-services/apis/sys-schedule-api.ts
Normal file
561
Web/src/api-services/apis/sys-schedule-api.ts
Normal file
@ -0,0 +1,561 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Admin.NET 通用权限开发平台
|
||||
* 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import globalAxios, { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios';
|
||||
import { Configuration } from '../configuration';
|
||||
// Some imports not used depending on template conditions
|
||||
// @ts-ignore
|
||||
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
|
||||
import { AddScheduleInput } from '../models';
|
||||
import { AdminResultInt32 } from '../models';
|
||||
import { AdminResultListSysSchedule } from '../models';
|
||||
import { AdminResultSysSchedule } from '../models';
|
||||
import { DeleteScheduleInput } from '../models';
|
||||
import { ListScheduleInput } from '../models';
|
||||
import { ScheduleInput } from '../models';
|
||||
import { UpdateScheduleInput } from '../models';
|
||||
/**
|
||||
* SysScheduleApi - axios parameter creator
|
||||
* @export
|
||||
*/
|
||||
export const SysScheduleApiAxiosParamCreator = function (configuration?: Configuration) {
|
||||
return {
|
||||
/**
|
||||
*
|
||||
* @summary 增加日程
|
||||
* @param {AddScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
apiSysScheduleAddPost: async (body?: AddScheduleInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/api/sysSchedule/add`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication Bearer required
|
||||
// http bearer authentication required
|
||||
if (configuration && configuration.accessToken) {
|
||||
const accessToken = typeof configuration.accessToken === 'function'
|
||||
? await configuration.accessToken()
|
||||
: await configuration.accessToken;
|
||||
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
|
||||
}
|
||||
|
||||
localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
|
||||
|
||||
const query = new URLSearchParams(localVarUrlObj.search);
|
||||
for (const key in localVarQueryParameter) {
|
||||
query.set(key, localVarQueryParameter[key]);
|
||||
}
|
||||
for (const key in options.params) {
|
||||
query.set(key, options.params[key]);
|
||||
}
|
||||
localVarUrlObj.search = (new URLSearchParams(query)).toString();
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
|
||||
localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
|
||||
|
||||
return {
|
||||
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 删除日程
|
||||
* @param {DeleteScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
apiSysScheduleDeletePost: async (body?: DeleteScheduleInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/api/sysSchedule/delete`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication Bearer required
|
||||
// http bearer authentication required
|
||||
if (configuration && configuration.accessToken) {
|
||||
const accessToken = typeof configuration.accessToken === 'function'
|
||||
? await configuration.accessToken()
|
||||
: await configuration.accessToken;
|
||||
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
|
||||
}
|
||||
|
||||
localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
|
||||
|
||||
const query = new URLSearchParams(localVarUrlObj.search);
|
||||
for (const key in localVarQueryParameter) {
|
||||
query.set(key, localVarQueryParameter[key]);
|
||||
}
|
||||
for (const key in options.params) {
|
||||
query.set(key, options.params[key]);
|
||||
}
|
||||
localVarUrlObj.search = (new URLSearchParams(query)).toString();
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
|
||||
localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
|
||||
|
||||
return {
|
||||
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取日程详情
|
||||
* @param {number} id
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
apiSysScheduleDetailIdGet: async (id: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
// verify required parameter 'id' is not null or undefined
|
||||
if (id === null || id === undefined) {
|
||||
throw new RequiredError('id','Required parameter id was null or undefined when calling apiSysScheduleDetailIdGet.');
|
||||
}
|
||||
const localVarPath = `/api/sysSchedule/detail/{id}`
|
||||
.replace(`{${"id"}}`, encodeURIComponent(String(id)));
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication Bearer required
|
||||
// http bearer authentication required
|
||||
if (configuration && configuration.accessToken) {
|
||||
const accessToken = typeof configuration.accessToken === 'function'
|
||||
? await configuration.accessToken()
|
||||
: await configuration.accessToken;
|
||||
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
|
||||
}
|
||||
|
||||
const query = new URLSearchParams(localVarUrlObj.search);
|
||||
for (const key in localVarQueryParameter) {
|
||||
query.set(key, localVarQueryParameter[key]);
|
||||
}
|
||||
for (const key in options.params) {
|
||||
query.set(key, options.params[key]);
|
||||
}
|
||||
localVarUrlObj.search = (new URLSearchParams(query)).toString();
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
|
||||
return {
|
||||
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取日程列表
|
||||
* @param {ListScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
apiSysSchedulePagePost: async (body?: ListScheduleInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/api/sysSchedule/page`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication Bearer required
|
||||
// http bearer authentication required
|
||||
if (configuration && configuration.accessToken) {
|
||||
const accessToken = typeof configuration.accessToken === 'function'
|
||||
? await configuration.accessToken()
|
||||
: await configuration.accessToken;
|
||||
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
|
||||
}
|
||||
|
||||
localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
|
||||
|
||||
const query = new URLSearchParams(localVarUrlObj.search);
|
||||
for (const key in localVarQueryParameter) {
|
||||
query.set(key, localVarQueryParameter[key]);
|
||||
}
|
||||
for (const key in options.params) {
|
||||
query.set(key, options.params[key]);
|
||||
}
|
||||
localVarUrlObj.search = (new URLSearchParams(query)).toString();
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
|
||||
localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
|
||||
|
||||
return {
|
||||
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 设置日程状态
|
||||
* @param {ScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
apiSysScheduleSetStatusPost: async (body?: ScheduleInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/api/sysSchedule/setStatus`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication Bearer required
|
||||
// http bearer authentication required
|
||||
if (configuration && configuration.accessToken) {
|
||||
const accessToken = typeof configuration.accessToken === 'function'
|
||||
? await configuration.accessToken()
|
||||
: await configuration.accessToken;
|
||||
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
|
||||
}
|
||||
|
||||
localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
|
||||
|
||||
const query = new URLSearchParams(localVarUrlObj.search);
|
||||
for (const key in localVarQueryParameter) {
|
||||
query.set(key, localVarQueryParameter[key]);
|
||||
}
|
||||
for (const key in options.params) {
|
||||
query.set(key, options.params[key]);
|
||||
}
|
||||
localVarUrlObj.search = (new URLSearchParams(query)).toString();
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
|
||||
localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
|
||||
|
||||
return {
|
||||
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 更新日程
|
||||
* @param {UpdateScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
apiSysScheduleUpdatePost: async (body?: UpdateScheduleInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/api/sysSchedule/update`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication Bearer required
|
||||
// http bearer authentication required
|
||||
if (configuration && configuration.accessToken) {
|
||||
const accessToken = typeof configuration.accessToken === 'function'
|
||||
? await configuration.accessToken()
|
||||
: await configuration.accessToken;
|
||||
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
|
||||
}
|
||||
|
||||
localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
|
||||
|
||||
const query = new URLSearchParams(localVarUrlObj.search);
|
||||
for (const key in localVarQueryParameter) {
|
||||
query.set(key, localVarQueryParameter[key]);
|
||||
}
|
||||
for (const key in options.params) {
|
||||
query.set(key, options.params[key]);
|
||||
}
|
||||
localVarUrlObj.search = (new URLSearchParams(query)).toString();
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
|
||||
localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
|
||||
|
||||
return {
|
||||
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* SysScheduleApi - functional programming interface
|
||||
* @export
|
||||
*/
|
||||
export const SysScheduleApiFp = function(configuration?: Configuration) {
|
||||
return {
|
||||
/**
|
||||
*
|
||||
* @summary 增加日程
|
||||
* @param {AddScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysScheduleAddPost(body?: AddScheduleInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
|
||||
const localVarAxiosArgs = await SysScheduleApiAxiosParamCreator(configuration).apiSysScheduleAddPost(body, options);
|
||||
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
|
||||
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 删除日程
|
||||
* @param {DeleteScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysScheduleDeletePost(body?: DeleteScheduleInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
|
||||
const localVarAxiosArgs = await SysScheduleApiAxiosParamCreator(configuration).apiSysScheduleDeletePost(body, options);
|
||||
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
|
||||
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取日程详情
|
||||
* @param {number} id
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysScheduleDetailIdGet(id: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSysSchedule>>> {
|
||||
const localVarAxiosArgs = await SysScheduleApiAxiosParamCreator(configuration).apiSysScheduleDetailIdGet(id, options);
|
||||
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
|
||||
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取日程列表
|
||||
* @param {ListScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysSchedulePagePost(body?: ListScheduleInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysSchedule>>> {
|
||||
const localVarAxiosArgs = await SysScheduleApiAxiosParamCreator(configuration).apiSysSchedulePagePost(body, options);
|
||||
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
|
||||
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 设置日程状态
|
||||
* @param {ScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysScheduleSetStatusPost(body?: ScheduleInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultInt32>>> {
|
||||
const localVarAxiosArgs = await SysScheduleApiAxiosParamCreator(configuration).apiSysScheduleSetStatusPost(body, options);
|
||||
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
|
||||
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 更新日程
|
||||
* @param {UpdateScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysScheduleUpdatePost(body?: UpdateScheduleInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
|
||||
const localVarAxiosArgs = await SysScheduleApiAxiosParamCreator(configuration).apiSysScheduleUpdatePost(body, options);
|
||||
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
|
||||
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* SysScheduleApi - factory interface
|
||||
* @export
|
||||
*/
|
||||
export const SysScheduleApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
|
||||
return {
|
||||
/**
|
||||
*
|
||||
* @summary 增加日程
|
||||
* @param {AddScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysScheduleAddPost(body?: AddScheduleInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
|
||||
return SysScheduleApiFp(configuration).apiSysScheduleAddPost(body, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 删除日程
|
||||
* @param {DeleteScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysScheduleDeletePost(body?: DeleteScheduleInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
|
||||
return SysScheduleApiFp(configuration).apiSysScheduleDeletePost(body, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取日程详情
|
||||
* @param {number} id
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysScheduleDetailIdGet(id: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSysSchedule>> {
|
||||
return SysScheduleApiFp(configuration).apiSysScheduleDetailIdGet(id, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取日程列表
|
||||
* @param {ListScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysSchedulePagePost(body?: ListScheduleInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysSchedule>> {
|
||||
return SysScheduleApiFp(configuration).apiSysSchedulePagePost(body, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 设置日程状态
|
||||
* @param {ScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysScheduleSetStatusPost(body?: ScheduleInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultInt32>> {
|
||||
return SysScheduleApiFp(configuration).apiSysScheduleSetStatusPost(body, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 更新日程
|
||||
* @param {UpdateScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysScheduleUpdatePost(body?: UpdateScheduleInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
|
||||
return SysScheduleApiFp(configuration).apiSysScheduleUpdatePost(body, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* SysScheduleApi - object-oriented interface
|
||||
* @export
|
||||
* @class SysScheduleApi
|
||||
* @extends {BaseAPI}
|
||||
*/
|
||||
export class SysScheduleApi extends BaseAPI {
|
||||
/**
|
||||
*
|
||||
* @summary 增加日程
|
||||
* @param {AddScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof SysScheduleApi
|
||||
*/
|
||||
public async apiSysScheduleAddPost(body?: AddScheduleInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
|
||||
return SysScheduleApiFp(this.configuration).apiSysScheduleAddPost(body, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @summary 删除日程
|
||||
* @param {DeleteScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof SysScheduleApi
|
||||
*/
|
||||
public async apiSysScheduleDeletePost(body?: DeleteScheduleInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
|
||||
return SysScheduleApiFp(this.configuration).apiSysScheduleDeletePost(body, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @summary 获取日程详情
|
||||
* @param {number} id
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof SysScheduleApi
|
||||
*/
|
||||
public async apiSysScheduleDetailIdGet(id: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSysSchedule>> {
|
||||
return SysScheduleApiFp(this.configuration).apiSysScheduleDetailIdGet(id, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @summary 获取日程列表
|
||||
* @param {ListScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof SysScheduleApi
|
||||
*/
|
||||
public async apiSysSchedulePagePost(body?: ListScheduleInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysSchedule>> {
|
||||
return SysScheduleApiFp(this.configuration).apiSysSchedulePagePost(body, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @summary 设置日程状态
|
||||
* @param {ScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof SysScheduleApi
|
||||
*/
|
||||
public async apiSysScheduleSetStatusPost(body?: ScheduleInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultInt32>> {
|
||||
return SysScheduleApiFp(this.configuration).apiSysScheduleSetStatusPost(body, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @summary 更新日程
|
||||
* @param {UpdateScheduleInput} [body]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof SysScheduleApi
|
||||
*/
|
||||
public async apiSysScheduleUpdatePost(body?: UpdateScheduleInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
|
||||
return SysScheduleApiFp(this.configuration).apiSysScheduleUpdatePost(body, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
}
|
||||
@ -168,6 +168,69 @@ export const SysWxOpenApiAxiosParamCreator = function (configuration?: Configura
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 验证签名 🔖
|
||||
* @param {string} [signature] 签名
|
||||
* @param {string} [timestamp] 时间戳
|
||||
* @param {string} [nonce] 随机数
|
||||
* @param {string} [echostr] 随机字符串
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
apiSysWxOpenVerifySignatureGet: async (signature?: string, timestamp?: string, nonce?: string, echostr?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/api/sysWxOpen/verifySignature`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication Bearer required
|
||||
// http bearer authentication required
|
||||
if (configuration && configuration.accessToken) {
|
||||
const accessToken = typeof configuration.accessToken === 'function'
|
||||
? await configuration.accessToken()
|
||||
: await configuration.accessToken;
|
||||
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
|
||||
}
|
||||
|
||||
if (signature !== undefined) {
|
||||
localVarQueryParameter['Signature'] = signature;
|
||||
}
|
||||
|
||||
if (timestamp !== undefined) {
|
||||
localVarQueryParameter['Timestamp'] = timestamp;
|
||||
}
|
||||
|
||||
if (nonce !== undefined) {
|
||||
localVarQueryParameter['Nonce'] = nonce;
|
||||
}
|
||||
|
||||
if (echostr !== undefined) {
|
||||
localVarQueryParameter['Echostr'] = echostr;
|
||||
}
|
||||
|
||||
const query = new URLSearchParams(localVarUrlObj.search);
|
||||
for (const key in localVarQueryParameter) {
|
||||
query.set(key, localVarQueryParameter[key]);
|
||||
}
|
||||
for (const key in options.params) {
|
||||
query.set(key, options.params[key]);
|
||||
}
|
||||
localVarUrlObj.search = (new URLSearchParams(query)).toString();
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
|
||||
return {
|
||||
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取微信用户OpenId 🔖
|
||||
@ -379,6 +442,23 @@ export const SysWxOpenApiFp = function(configuration?: Configuration) {
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 验证签名 🔖
|
||||
* @param {string} [signature] 签名
|
||||
* @param {string} [timestamp] 时间戳
|
||||
* @param {string} [nonce] 随机数
|
||||
* @param {string} [echostr] 随机字符串
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysWxOpenVerifySignatureGet(signature?: string, timestamp?: string, nonce?: string, echostr?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<string>>> {
|
||||
const localVarAxiosArgs = await SysWxOpenApiAxiosParamCreator(configuration).apiSysWxOpenVerifySignatureGet(signature, timestamp, nonce, echostr, options);
|
||||
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
|
||||
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取微信用户OpenId 🔖
|
||||
@ -460,6 +540,19 @@ export const SysWxOpenApiFactory = function (configuration?: Configuration, base
|
||||
async apiSysWxOpenSendSubscribeMessagePost(body?: SendSubscribeMessageInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
|
||||
return SysWxOpenApiFp(configuration).apiSysWxOpenSendSubscribeMessagePost(body, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 验证签名 🔖
|
||||
* @param {string} [signature] 签名
|
||||
* @param {string} [timestamp] 时间戳
|
||||
* @param {string} [nonce] 随机数
|
||||
* @param {string} [echostr] 随机字符串
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async apiSysWxOpenVerifySignatureGet(signature?: string, timestamp?: string, nonce?: string, echostr?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<string>> {
|
||||
return SysWxOpenApiFp(configuration).apiSysWxOpenVerifySignatureGet(signature, timestamp, nonce, echostr, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 获取微信用户OpenId 🔖
|
||||
@ -533,6 +626,20 @@ export class SysWxOpenApi extends BaseAPI {
|
||||
public async apiSysWxOpenSendSubscribeMessagePost(body?: SendSubscribeMessageInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
|
||||
return SysWxOpenApiFp(this.configuration).apiSysWxOpenSendSubscribeMessagePost(body, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @summary 验证签名 🔖
|
||||
* @param {string} [signature] 签名
|
||||
* @param {string} [timestamp] 时间戳
|
||||
* @param {string} [nonce] 随机数
|
||||
* @param {string} [echostr] 随机字符串
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof SysWxOpenApi
|
||||
*/
|
||||
public async apiSysWxOpenVerifySignatureGet(signature?: string, timestamp?: string, nonce?: string, echostr?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<string>> {
|
||||
return SysWxOpenApiFp(this.configuration).apiSysWxOpenVerifySignatureGet(signature, timestamp, nonce, echostr, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @summary 获取微信用户OpenId 🔖
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { Filter } from './filter';
|
||||
import { Search } from './search';
|
||||
/**
|
||||
*
|
||||
*
|
||||
@ -20,6 +22,26 @@
|
||||
*/
|
||||
export interface AddCodeGenInput {
|
||||
|
||||
/**
|
||||
* @type {Search}
|
||||
* @memberof AddCodeGenInput
|
||||
*/
|
||||
search?: Search;
|
||||
|
||||
/**
|
||||
* 模糊查询关键字
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddCodeGenInput
|
||||
*/
|
||||
keyword?: string | null;
|
||||
|
||||
/**
|
||||
* @type {Filter}
|
||||
* @memberof AddCodeGenInput
|
||||
*/
|
||||
filter?: Filter;
|
||||
|
||||
/**
|
||||
* 当前页码
|
||||
*
|
||||
|
||||
141
Web/src/api-services/models/add-schedule-input.ts
Normal file
141
Web/src/api-services/models/add-schedule-input.ts
Normal file
@ -0,0 +1,141 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Admin.NET 通用权限开发平台
|
||||
* 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { FinishStatusEnum } from './finish-status-enum';
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @export
|
||||
* @interface AddScheduleInput
|
||||
*/
|
||||
export interface AddScheduleInput {
|
||||
|
||||
/**
|
||||
* 雪花Id
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
id?: number;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
createTime?: Date;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
updateTime?: Date | null;
|
||||
|
||||
/**
|
||||
* 创建者Id
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
createUserId?: number | null;
|
||||
|
||||
/**
|
||||
* 创建者姓名
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
createUserName?: string | null;
|
||||
|
||||
/**
|
||||
* 修改者Id
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
updateUserId?: number | null;
|
||||
|
||||
/**
|
||||
* 修改者姓名
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
updateUserName?: string | null;
|
||||
|
||||
/**
|
||||
* 软删除
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
isDelete?: boolean;
|
||||
|
||||
/**
|
||||
* 租户Id
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
tenantId?: number | null;
|
||||
|
||||
/**
|
||||
* 用户Id
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
userId?: number;
|
||||
|
||||
/**
|
||||
* 日程日期
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
scheduleTime?: Date | null;
|
||||
|
||||
/**
|
||||
* 开始时间
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
startTime?: string | null;
|
||||
|
||||
/**
|
||||
* 结束时间
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
endTime?: string | null;
|
||||
|
||||
/**
|
||||
* @type {FinishStatusEnum}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
status?: FinishStatusEnum;
|
||||
|
||||
/**
|
||||
* 日程内容
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddScheduleInput
|
||||
*/
|
||||
content: string;
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Admin.NET 通用权限开发平台
|
||||
* 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { SysSchedule } from './sys-schedule';
|
||||
/**
|
||||
* 全局返回结果
|
||||
*
|
||||
* @export
|
||||
* @interface AdminResultListSysSchedule
|
||||
*/
|
||||
export interface AdminResultListSysSchedule {
|
||||
|
||||
/**
|
||||
* 状态码
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AdminResultListSysSchedule
|
||||
*/
|
||||
code?: number;
|
||||
|
||||
/**
|
||||
* 类型success、warning、error
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AdminResultListSysSchedule
|
||||
*/
|
||||
type?: string | null;
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AdminResultListSysSchedule
|
||||
*/
|
||||
message?: string | null;
|
||||
|
||||
/**
|
||||
* 数据
|
||||
*
|
||||
* @type {Array<SysSchedule>}
|
||||
* @memberof AdminResultListSysSchedule
|
||||
*/
|
||||
result?: Array<SysSchedule> | null;
|
||||
|
||||
/**
|
||||
* 附加数据
|
||||
*
|
||||
* @type {any}
|
||||
* @memberof AdminResultListSysSchedule
|
||||
*/
|
||||
extras?: any | null;
|
||||
|
||||
/**
|
||||
* 时间
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof AdminResultListSysSchedule
|
||||
*/
|
||||
time?: Date;
|
||||
}
|
||||
69
Web/src/api-services/models/admin-result-sys-schedule.ts
Normal file
69
Web/src/api-services/models/admin-result-sys-schedule.ts
Normal file
@ -0,0 +1,69 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Admin.NET 通用权限开发平台
|
||||
* 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { SysSchedule } from './sys-schedule';
|
||||
/**
|
||||
* 全局返回结果
|
||||
*
|
||||
* @export
|
||||
* @interface AdminResultSysSchedule
|
||||
*/
|
||||
export interface AdminResultSysSchedule {
|
||||
|
||||
/**
|
||||
* 状态码
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AdminResultSysSchedule
|
||||
*/
|
||||
code?: number;
|
||||
|
||||
/**
|
||||
* 类型success、warning、error
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AdminResultSysSchedule
|
||||
*/
|
||||
type?: string | null;
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AdminResultSysSchedule
|
||||
*/
|
||||
message?: string | null;
|
||||
|
||||
/**
|
||||
* @type {SysSchedule}
|
||||
* @memberof AdminResultSysSchedule
|
||||
*/
|
||||
result?: SysSchedule;
|
||||
|
||||
/**
|
||||
* 附加数据
|
||||
*
|
||||
* @type {any}
|
||||
* @memberof AdminResultSysSchedule
|
||||
*/
|
||||
extras?: any | null;
|
||||
|
||||
/**
|
||||
* 时间
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof AdminResultSysSchedule
|
||||
*/
|
||||
time?: Date;
|
||||
}
|
||||
30
Web/src/api-services/models/delete-schedule-input.ts
Normal file
30
Web/src/api-services/models/delete-schedule-input.ts
Normal file
@ -0,0 +1,30 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Admin.NET 通用权限开发平台
|
||||
* 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @export
|
||||
* @interface DeleteScheduleInput
|
||||
*/
|
||||
export interface DeleteScheduleInput {
|
||||
|
||||
/**
|
||||
* 主键Id
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof DeleteScheduleInput
|
||||
*/
|
||||
id: number;
|
||||
}
|
||||
25
Web/src/api-services/models/filter-logic-enum.ts
Normal file
25
Web/src/api-services/models/filter-logic-enum.ts
Normal file
@ -0,0 +1,25 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Admin.NET 通用权限开发平台
|
||||
* 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 过滤条件<br /> 并且 And = 0<br /> 或者 Or = 1<br /> 异或 Xor = 2<br />
|
||||
* @export
|
||||
* @enum {string}
|
||||
*/
|
||||
export enum FilterLogicEnum {
|
||||
NUMBER_0 = 0,
|
||||
NUMBER_1 = 1,
|
||||
NUMBER_2 = 2
|
||||
}
|
||||
|
||||
31
Web/src/api-services/models/filter-operator-enum.ts
Normal file
31
Web/src/api-services/models/filter-operator-enum.ts
Normal file
@ -0,0 +1,31 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Admin.NET 通用权限开发平台
|
||||
* 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 过滤逻辑运算符<br /> 等于 EQ = 0<br /> 不等于 NEQ = 1<br /> 小于 LT = 2<br /> 小于等于 LTE = 3<br /> 大于 GT = 4<br /> 大于等于 GTE = 5<br /> 开始包含 StartsWith = 6<br /> 末尾包含 EndsWith = 7<br /> 包含 Contains = 8<br />
|
||||
* @export
|
||||
* @enum {string}
|
||||
*/
|
||||
export enum FilterOperatorEnum {
|
||||
NUMBER_0 = 0,
|
||||
NUMBER_1 = 1,
|
||||
NUMBER_2 = 2,
|
||||
NUMBER_3 = 3,
|
||||
NUMBER_4 = 4,
|
||||
NUMBER_5 = 5,
|
||||
NUMBER_6 = 6,
|
||||
NUMBER_7 = 7,
|
||||
NUMBER_8 = 8
|
||||
}
|
||||
|
||||
61
Web/src/api-services/models/filter.ts
Normal file
61
Web/src/api-services/models/filter.ts
Normal file
@ -0,0 +1,61 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Admin.NET 通用权限开发平台
|
||||
* 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { Filter } from './filter';
|
||||
import { FilterLogicEnum } from './filter-logic-enum';
|
||||
import { FilterOperatorEnum } from './filter-operator-enum';
|
||||
/**
|
||||
* 筛选过滤条件
|
||||
*
|
||||
* @export
|
||||
* @interface Filter
|
||||
*/
|
||||
export interface Filter {
|
||||
|
||||
/**
|
||||
* @type {FilterLogicEnum}
|
||||
* @memberof Filter
|
||||
*/
|
||||
logic?: FilterLogicEnum;
|
||||
|
||||
/**
|
||||
* 筛选过滤条件子项
|
||||
*
|
||||
* @type {Array<Filter>}
|
||||
* @memberof Filter
|
||||
*/
|
||||
filters?: Array<Filter> | null;
|
||||
|
||||
/**
|
||||
* 字段名称
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof Filter
|
||||
*/
|
||||
field?: string | null;
|
||||
|
||||
/**
|
||||
* @type {FilterOperatorEnum}
|
||||
* @memberof Filter
|
||||
*/
|
||||
operator?: FilterOperatorEnum;
|
||||
|
||||
/**
|
||||
* 字段值
|
||||
*
|
||||
* @type {any}
|
||||
* @memberof Filter
|
||||
*/
|
||||
value?: any | null;
|
||||
}
|
||||
24
Web/src/api-services/models/finish-status-enum.ts
Normal file
24
Web/src/api-services/models/finish-status-enum.ts
Normal file
@ -0,0 +1,24 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Admin.NET 通用权限开发平台
|
||||
* 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 完成状态枚举<br /> 未完成 UnFinish = 0<br /> 已完成 Finish = 1<br />
|
||||
* @export
|
||||
* @enum {string}
|
||||
*/
|
||||
export enum FinishStatusEnum {
|
||||
NUMBER_0 = 0,
|
||||
NUMBER_1 = 1
|
||||
}
|
||||
|
||||
@ -13,13 +13,14 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* 性别枚举<br /> 男 Male = 1<br /> 女 Female = 2<br /> 其他 Other = 3<br />
|
||||
* 性别枚举(GB/T 2261.1-2003)<br /> 未知的性别 Unknown = 0<br /> 男性 Male = 1<br /> 女性 Female = 2<br /> 未说明的性别 Unspecified = 9<br />
|
||||
* @export
|
||||
* @enum {string}
|
||||
*/
|
||||
export enum GenderEnum {
|
||||
NUMBER_0 = 0,
|
||||
NUMBER_1 = 1,
|
||||
NUMBER_2 = 2,
|
||||
NUMBER_3 = 3
|
||||
NUMBER_9 = 9
|
||||
}
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ export * from './add-pos-input';
|
||||
export * from './add-print-input';
|
||||
export * from './add-region-input';
|
||||
export * from './add-role-input';
|
||||
export * from './add-schedule-input';
|
||||
export * from './add-subscribe-message-template-input';
|
||||
export * from './add-sys-ldap-input';
|
||||
export * from './add-tenant-input';
|
||||
@ -55,6 +56,7 @@ export * from './admin-result-list-sys-menu';
|
||||
export * from './admin-result-list-sys-notice';
|
||||
export * from './admin-result-list-sys-org';
|
||||
export * from './admin-result-list-sys-region';
|
||||
export * from './admin-result-list-sys-schedule';
|
||||
export * from './admin-result-list-sys-user';
|
||||
export * from './admin-result-list-sys-user-ext-org';
|
||||
export * from './admin-result-list-table-output';
|
||||
@ -98,6 +100,7 @@ export * from './admin-result-sys-ldap';
|
||||
export * from './admin-result-sys-log-ex';
|
||||
export * from './admin-result-sys-log-op';
|
||||
export * from './admin-result-sys-print';
|
||||
export * from './admin-result-sys-schedule';
|
||||
export * from './admin-result-sys-user';
|
||||
export * from './admin-result-sys-wechat-pay';
|
||||
export * from './admin-result-visual-db-table';
|
||||
@ -167,6 +170,7 @@ export * from './delete-pos-input';
|
||||
export * from './delete-print-input';
|
||||
export * from './delete-region-input';
|
||||
export * from './delete-role-input';
|
||||
export * from './delete-schedule-input';
|
||||
export * from './delete-sys-ldap-input';
|
||||
export * from './delete-tenant-input';
|
||||
export * from './delete-user-input';
|
||||
@ -183,6 +187,10 @@ export * from './field-attributes';
|
||||
export * from './field-info';
|
||||
export * from './file-input';
|
||||
export * from './file-output';
|
||||
export * from './filter';
|
||||
export * from './filter-logic-enum';
|
||||
export * from './filter-operator-enum';
|
||||
export * from './finish-status-enum';
|
||||
export * from './from';
|
||||
export * from './gen-auth-url-input';
|
||||
export * from './gender-enum';
|
||||
@ -204,6 +212,7 @@ export * from './job-detail-input';
|
||||
export * from './job-detail-output';
|
||||
export * from './job-trigger-input';
|
||||
export * from './layout-kind';
|
||||
export * from './list-schedule-input';
|
||||
export * from './log-input';
|
||||
export * from './log-level';
|
||||
export * from './log-vis-output';
|
||||
@ -273,7 +282,9 @@ export * from './role-output';
|
||||
export * from './runtime-field-handle';
|
||||
export * from './runtime-method-handle';
|
||||
export * from './runtime-type-handle';
|
||||
export * from './schedule-input';
|
||||
export * from './schema-serialization-mode';
|
||||
export * from './search';
|
||||
export * from './security-rule-set';
|
||||
export * from './send-subscribe-message-input';
|
||||
export * from './serialization-format';
|
||||
@ -338,6 +349,7 @@ export * from './sys-org';
|
||||
export * from './sys-plugin';
|
||||
export * from './sys-print';
|
||||
export * from './sys-region';
|
||||
export * from './sys-schedule';
|
||||
export * from './sys-user';
|
||||
export * from './sys-user-ext-org';
|
||||
export * from './sys-wechat-pay';
|
||||
@ -370,6 +382,7 @@ export * from './update-pos-input';
|
||||
export * from './update-print-input';
|
||||
export * from './update-region-input';
|
||||
export * from './update-role-input';
|
||||
export * from './update-schedule-input';
|
||||
export * from './update-sys-ldap-input';
|
||||
export * from './update-tenant-input';
|
||||
export * from './update-user-input';
|
||||
|
||||
@ -28,6 +28,14 @@ export interface InfoSaveInput {
|
||||
*/
|
||||
sysLogoBase64?: string | null;
|
||||
|
||||
/**
|
||||
* 系统图标文件名
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof InfoSaveInput
|
||||
*/
|
||||
sysLogoFileName?: string | null;
|
||||
|
||||
/**
|
||||
* 系统主标题
|
||||
*
|
||||
|
||||
34
Web/src/api-services/models/list-schedule-input.ts
Normal file
34
Web/src/api-services/models/list-schedule-input.ts
Normal file
@ -0,0 +1,34 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Admin.NET 通用权限开发平台
|
||||
* 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @export
|
||||
* @interface ListScheduleInput
|
||||
*/
|
||||
export interface ListScheduleInput {
|
||||
|
||||
/**
|
||||
* @type {Date}
|
||||
* @memberof ListScheduleInput
|
||||
*/
|
||||
startTime?: Date | null;
|
||||
|
||||
/**
|
||||
* @type {Date}
|
||||
* @memberof ListScheduleInput
|
||||
*/
|
||||
endTime?: Date | null;
|
||||
}
|
||||
@ -12,6 +12,8 @@
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { Filter } from './filter';
|
||||
import { Search } from './search';
|
||||
/**
|
||||
*
|
||||
*
|
||||
@ -20,6 +22,26 @@
|
||||
*/
|
||||
export interface OAuthUserInput {
|
||||
|
||||
/**
|
||||
* @type {Search}
|
||||
* @memberof OAuthUserInput
|
||||
*/
|
||||
search?: Search;
|
||||
|
||||
/**
|
||||
* 模糊查询关键字
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof OAuthUserInput
|
||||
*/
|
||||
keyword?: string | null;
|
||||
|
||||
/**
|
||||
* @type {Filter}
|
||||
* @memberof OAuthUserInput
|
||||
*/
|
||||
filter?: Filter;
|
||||
|
||||
/**
|
||||
* 当前页码
|
||||
*
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { Filter } from './filter';
|
||||
import { Search } from './search';
|
||||
/**
|
||||
* 代码生成参数类
|
||||
*
|
||||
@ -20,6 +22,26 @@
|
||||
*/
|
||||
export interface PageCodeGenInput {
|
||||
|
||||
/**
|
||||
* @type {Search}
|
||||
* @memberof PageCodeGenInput
|
||||
*/
|
||||
search?: Search;
|
||||
|
||||
/**
|
||||
* 模糊查询关键字
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PageCodeGenInput
|
||||
*/
|
||||
keyword?: string | null;
|
||||
|
||||
/**
|
||||
* @type {Filter}
|
||||
* @memberof PageCodeGenInput
|
||||
*/
|
||||
filter?: Filter;
|
||||
|
||||
/**
|
||||
* 当前页码
|
||||
*
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { Filter } from './filter';
|
||||
import { Search } from './search';
|
||||
/**
|
||||
*
|
||||
*
|
||||
@ -20,6 +22,26 @@
|
||||
*/
|
||||
export interface PageConfigInput {
|
||||
|
||||
/**
|
||||
* @type {Search}
|
||||
* @memberof PageConfigInput
|
||||
*/
|
||||
search?: Search;
|
||||
|
||||
/**
|
||||
* 模糊查询关键字
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PageConfigInput
|
||||
*/
|
||||
keyword?: string | null;
|
||||
|
||||
/**
|
||||
* @type {Filter}
|
||||
* @memberof PageConfigInput
|
||||
*/
|
||||
filter?: Filter;
|
||||
|
||||
/**
|
||||
* 当前页码
|
||||
*
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { Filter } from './filter';
|
||||
import { Search } from './search';
|
||||
/**
|
||||
*
|
||||
*
|
||||
@ -20,6 +22,26 @@
|
||||
*/
|
||||
export interface PageDictDataInput {
|
||||
|
||||
/**
|
||||
* @type {Search}
|
||||
* @memberof PageDictDataInput
|
||||
*/
|
||||
search?: Search;
|
||||
|
||||
/**
|
||||
* 模糊查询关键字
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PageDictDataInput
|
||||
*/
|
||||
keyword?: string | null;
|
||||
|
||||
/**
|
||||
* @type {Filter}
|
||||
* @memberof PageDictDataInput
|
||||
*/
|
||||
filter?: Filter;
|
||||
|
||||
/**
|
||||
* 当前页码
|
||||
*
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { Filter } from './filter';
|
||||
import { Search } from './search';
|
||||
/**
|
||||
*
|
||||
*
|
||||
@ -20,6 +22,26 @@
|
||||
*/
|
||||
export interface PageDictTypeInput {
|
||||
|
||||
/**
|
||||
* @type {Search}
|
||||
* @memberof PageDictTypeInput
|
||||
*/
|
||||
search?: Search;
|
||||
|
||||
/**
|
||||
* 模糊查询关键字
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PageDictTypeInput
|
||||
*/
|
||||
keyword?: string | null;
|
||||
|
||||
/**
|
||||
* @type {Filter}
|
||||
* @memberof PageDictTypeInput
|
||||
*/
|
||||
filter?: Filter;
|
||||
|
||||
/**
|
||||
* 当前页码
|
||||
*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user