Merge pull request 'main' (#3) from Admin.NET/Admin.NET.Pro:main into main

Reviewed-on: http://101.43.53.74:3000/shuerchoi/Admin.NET.Pro/pulls/3
This commit is contained in:
shuerchoi 2024-07-17 14:12:34 +08:00
commit 3e88f46aa4
99 changed files with 2614 additions and 386 deletions

View File

@ -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))

View File

@ -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.6" />
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.4.6" />
<PackageReference Include="Furion.Pure" Version="4.9.4.6" />
<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.1" />
<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.1047" />
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1049" />
<PackageReference Include="UAParser" Version="3.1.47" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
</ItemGroup>

View File

@ -12,91 +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>
/// 行政区域同步层级 1-省级,2-市级,3-区县级,4-街道级,5-村级
/// </summary>
public const string SysRegionSyncLevel = "sys_region_sync_level";
/// <summary>
/// 日志保留天数
/// </summary>
public const string SysLogRetentionDays = "sys_log_retention_days";
/// <summary>
/// 日志分组名称
/// </summary>

View File

@ -11,6 +11,76 @@ namespace Admin.NET.Core;
/// </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>

View File

@ -27,13 +27,13 @@ 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>

View File

@ -0,0 +1,34 @@
// 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 = 256)]
[Required, MaxLength(256)]
public virtual string Content { get; set; }
}

View File

@ -1,4 +1,4 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
@ -25,13 +25,13 @@ public enum FilterOperatorEnum
NEQ,
/// <summary>
/// 小于(<)
/// 小于<![CDATA[ < ]]>
/// </summary>
[Description("小于")]
LT,
/// <summary>
/// 小于等于(<=)
/// 小于等于<![CDATA[ <= ]]>
/// </summary>
[Description("小于等于")]
LTE,

View File

@ -261,9 +261,9 @@ public static partial class ObjectExtension
public static string ParseToDateTimeForRep(this string str)
{
if (string.IsNullOrWhiteSpace(str))
str = $"{DateTime.Now.Year}/{DateTime.Now.Month}/{DateTime.Now.Day}";
str = $"{DateTime.UtcNow.Year}/{DateTime.UtcNow.Month}/{DateTime.UtcNow.Day}";
var date = DateTime.Now;
var date = DateTime.UtcNow;
var reg = new Regex(@"(\{.+?})");
var match = reg.Matches(str);
match.ToList().ForEach(u =>

View File

@ -31,22 +31,28 @@ public static class SqlSugarFilterExtension
/// <param name="type"></param>
/// <param name="owners"></param>
/// <returns></returns>
public static LambdaExpression GetConditionExpression<T>(this Type type, List<long> owners)
where T : Attribute
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(filedName =>
fieldNames.ForEach(fieldName =>
{
owners.ForEach(owner =>
{
Expression left = Expression.Equal(
Expression.Property(parameter, type.GetProperty(filedName)),
Expression.Constant(owner)
);
right = Expression.Or(left, right);
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 });

View File

@ -52,7 +52,7 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
UserId = _userManager.UserId,
UserName = _userManager.Account,
RealName = _userManager.RealName,
Time = DateTime.Now,
Time = DateTime.UtcNow,
Ip = httpContext.GetRemoteIpAddressToIPv4(true),
Browser = httpContext.GetClientBrowser(),
Os = httpContext.GetClientOs(),
@ -61,7 +61,7 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
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);
}
@ -102,7 +102,7 @@ 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);
}

View File

@ -143,7 +143,7 @@ public class EnumToDictJob : IJob
var originColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"【{DateTime.Now}】系统枚举转换字典");
Console.WriteLine($"【{DateTime.UtcNow}】系统枚举转换字典");
Console.ForegroundColor = originColor;
}
}

View File

@ -31,12 +31,12 @@ 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.UtcNow.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除访问日志
await logOpRep.CopyNew().AsDeleteable().Where(u => u.CreateTime < DateTime.UtcNow.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除操作日志
await logDiffRep.CopyNew().AsDeleteable().Where(u => u.CreateTime < DateTime.UtcNow.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除差异日志
string msg = $"【{DateTime.Now}】清理系统日志成功,删除 {daysAgo} 天前的日志数据!";
string msg = $"【{DateTime.UtcNow}】清理系统日志成功,删除 {daysAgo} 天前的日志数据!";
var originColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(msg);

View File

@ -34,7 +34,7 @@ public class OnlineUserJob : IJob
// 缓存租户列表
await serviceScope.ServiceProvider.GetRequiredService<SysTenantService>().CacheTenant();
string msg = $"【{DateTime.Now}】清理在线用户成功!服务已重启...";
string msg = $"【{DateTime.UtcNow}】清理在线用户成功!服务已重启...";
var originColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(msg);

View File

@ -55,11 +55,11 @@ public class RoleApiJob : IJob
var originColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine($"【{DateTime.Now}】初始化管理员角色接口资源");
Console.WriteLine($"【{DateTime.UtcNow}】初始化管理员角色接口资源");
Console.ForegroundColor = originColor;
// 自定义日志
_logger.LogInformation($"【{DateTime.Now}】初始化管理员角色接口资源");
_logger.LogInformation($"【{DateTime.UtcNow}】初始化管理员角色接口资源");
await Task.CompletedTask;
}

View File

@ -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,

View File

@ -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();
@ -61,7 +61,7 @@ public class ElasticSearchLoggingWriter : IDatabaseLoggingWriter, IDisposable
var sysLogOp = new SysLogOp
{
Id = DateTime.Now.Ticks,
Id = DateTime.UtcNow.Ticks,
ControllerName = loggingMonitor.controllerName,
ActionName = loggingMonitor.actionTypeName,
DisplayTitle = loggingMonitor.displayTitle,

View File

@ -42,7 +42,7 @@
// Browser = context.HttpContext.Request.Headers["User-Agent"],
// TraceId = App.GetTraceId(),
// ThreadId = App.GetThreadId(),
// LogDateTime = DateTime.Now,
// LogDateTime = DateTime.UtcNow,
// LogLevel = LogLevel.Error
// };

View File

@ -44,7 +44,7 @@ public static class LoggingSetup
{
options.WithTraceId = true; // 显示线程Id
options.WithStackFrame = true; // 显示程序集
options.FileNameRule = fileName => string.Format(fileName, DateTime.Now, logLevel.ToString()); // 每天创建一个文件
options.FileNameRule = fileName => string.Format(fileName, DateTime.UtcNow, logLevel.ToString()); // 每天创建一个文件
options.WriteFilter = logMsg => logMsg.LogLevel == logLevel; // 日志级别
options.HandleWriteError = (writeError) => // 写入失败时启用备用文件
{

View File

@ -19,28 +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=1300000000231, Name="行政区域同步层级", Code="sys_region_sync_level", 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="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") },
};
}
}

View File

@ -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)
@ -240,7 +240,7 @@ public class SysAuthService : IDynamicApiController, ITransient
// 更新用户登录信息
user.LastLoginIp = _httpContextAccessor.HttpContext.GetRemoteIpAddressToIPv4(true);
(user.LastLoginAddress, double? longitude, double? latitude) = CommonUtil.GetIpAddress(user.LastLoginIp);
user.LastLoginTime = DateTime.Now;
user.LastLoginTime = DateTime.UtcNow;
user.LastLoginDevice = CommonUtil.GetClientDeviceInfo(_httpContextAccessor.HttpContext?.Request?.Headers?.UserAgent);
await _sysUserRep.AsUpdateable(user).UpdateColumns(u => new
{
@ -277,7 +277,7 @@ public class SysAuthService : IDynamicApiController, ITransient
// 获取水印文字(若系统水印为空则全局为空)
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.UtcNow}";
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;
}

View File

@ -4,6 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Hardware.Info;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Controllers;
using Org.BouncyCastle.Crypto.Parameters;
@ -123,7 +124,7 @@ public class SysCommonService : IDynamicApiController, ITransient
}
/// <summary>
/// 下载标记错误的临时 Excel全局
/// 下载标记错误的临时 Excel全局 🔖
/// </summary>
/// <returns></returns>
[DisplayName("下载标记错误的临时 Excel")]
@ -137,7 +138,34 @@ public class SysCommonService : IDynamicApiController, ITransient
return await Task.FromResult(new FileStreamResult(resultStream, "application/octet-stream")
{
FileDownloadName = $"{(string.IsNullOrEmpty(fileName) ? "_" + DateTime.Now.ToString("yyyyMMddhhmmss") : fileName)}.xlsx"
FileDownloadName = $"{(string.IsNullOrEmpty(fileName) ? "_" + DateTime.UtcNow.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}");
}
}
}

View File

@ -195,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;
}
@ -207,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;
}

View File

@ -528,7 +528,7 @@ public class SysDatabaseService : IDynamicApiController, ITransient
Directory.CreateDirectory(backupDirectory);
// 构建备份文件名
string backupFileName = $"backup_{DateTime.Now:yyyyMMddHHmmss}.sql";
string backupFileName = $"backup_{DateTime.UtcNow:yyyyMMddHHmmss}.sql";
string backupFilePath = Path.Combine(backupDirectory, backupFileName);
// 启动pg_dump进程进行备份

View File

@ -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(); // 后缀

View File

@ -11,7 +11,7 @@ namespace Admin.NET.Core.Service;
/// </summary>
public class JobClusterServer : IJobClusterServer
{
private readonly Random rd = new(DateTime.Now.Millisecond);
private readonly Random rd = new(DateTime.UtcNow.Millisecond);
public JobClusterServer()
{

View File

@ -30,7 +30,7 @@ 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, stoppingToken);

View File

@ -74,6 +74,6 @@ public class SysLogExService : IDynamicApiController, ITransient
IExcelExporter excelExporter = new ExcelExporter();
var res = await excelExporter.ExportAsByteArray(logExList);
return new FileStreamResult(new MemoryStream(res), "application/octet-stream") { FileDownloadName = DateTime.Now.ToString("yyyyMMddHHmm") + "异常日志.xlsx" };
return new FileStreamResult(new MemoryStream(res), "application/octet-stream") { FileDownloadName = DateTime.UtcNow.ToString("yyyyMMddHHmm") + "异常日志.xlsx" };
}
}

View File

@ -74,6 +74,6 @@ public class SysLogOpService : IDynamicApiController, ITransient
IExcelExporter excelExporter = new ExcelExporter();
var res = await excelExporter.ExportAsByteArray(logOpList);
return new FileStreamResult(new MemoryStream(res), "application/octet-stream") { FileDownloadName = DateTime.Now.ToString("yyyyMMddHHmm") + "操作日志.xlsx" };
return new FileStreamResult(new MemoryStream(res), "application/octet-stream") { FileDownloadName = DateTime.UtcNow.ToString("yyyyMMddHHmm") + "操作日志.xlsx" };
}
}

View File

@ -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);

View File

@ -101,7 +101,7 @@ public class SysNoticeService : IDynamicApiController, ITransient
public async Task Public(NoticeInput input)
{
// 更新发布状态和时间
await _sysNoticeRep.UpdateAsync(u => new SysNotice() { Status = NoticeStatusEnum.PUBLIC, PublicTime = DateTime.Now }, u => u.Id == input.Id);
await _sysNoticeRep.UpdateAsync(u => new SysNotice() { Status = NoticeStatusEnum.PUBLIC, PublicTime = DateTime.UtcNow }, u => u.Id == input.Id);
var notice = await _sysNoticeRep.GetFirstAsync(u => u.Id == input.Id);
@ -131,7 +131,7 @@ public class SysNoticeService : IDynamicApiController, ITransient
await _sysNoticeUserRep.UpdateAsync(u => new SysNoticeUser
{
ReadStatus = NoticeUserStatusEnum.READ,
ReadTime = DateTime.Now
ReadTime = DateTime.UtcNow
}, u => u.NoticeId == input.Id && u.UserId == _userManager.UserId);
}

View File

@ -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)

View File

@ -149,7 +149,7 @@ public class SysRegionService : IDynamicApiController, ITransient
[DisplayName("同步行政区域")]
public async Task Sync()
{
var syncLevel = await _sysConfigService.GetConfigValue<int>(CommonConst.SysRegionSyncLevel);
var syncLevel = await _sysConfigService.GetConfigValue<int>(ConfigConst.SysRegionSyncLevel);
if (syncLevel < 1 || syncLevel > 5)
syncLevel = 3;//默认区县级
var context = BrowsingContext.New(AngleSharp.Configuration.Default.WithDefaultLoader());

View File

@ -0,0 +1,31 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
public class ScheduleInput
{
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
{
}

View File

@ -0,0 +1,87 @@
// 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(ScheduleInput 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.CreateTime, 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);
}
}

View File

@ -62,7 +62,7 @@ public class SysServerService : IDynamicApiController, ITransient
public dynamic GetServerUsed()
{
var programStartTime = Process.GetCurrentProcess().StartTime;
var totalMilliseconds = (DateTime.Now - programStartTime).TotalMilliseconds.ToString();
var totalMilliseconds = (DateTime.UtcNow - programStartTime).TotalMilliseconds.ToString();
var ts = totalMilliseconds.Contains('.') ? totalMilliseconds.Split('.')[0] : totalMilliseconds;
var programRunTime = DateTimeUtil.FormatTime(ts.ParseToLong());

View File

@ -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,
@ -375,7 +375,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;

View File

@ -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);
@ -317,7 +317,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();

View File

@ -125,20 +125,20 @@ public class VerifySignatureInput
/// <summary>
/// 签名
/// </summary>
public string signature { get; set; }
public string Signature { get; set; }
/// <summary>
/// 时间戳
/// </summary>
public string timestamp { get; set; }
public string Timestamp { get; set; }
/// <summary>
/// 随机数
/// </summary>
public string nonce { get; set; }
public string Nonce { get; set; }
/// <summary>
/// 随机字符串
/// </summary>
public string echostr { get; set; }
public string Echostr { get; set; }
}

View File

@ -68,7 +68,7 @@ public class SysWechatPayService : IDynamicApiController, ITransient
[DisplayName("微信支付统一下单获取Id(商户直连)")]
public async Task<CreatePayTransactionOutput> CreatePayTransaction([FromBody] WechatPayTransactionInput input)
{
string outTradeNumber = DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000); // 微信需要的订单号(唯一)
string outTradeNumber = DateTimeOffset.UtcNow.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000); // 微信需要的订单号(唯一)
//检查订单信息是否已存在(使用“商户交易单号+状态”唯一性判断)
var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OrderId == input.OrderId && u.OrderStatus == input.OrderStatus);
@ -84,7 +84,7 @@ public class SysWechatPayService : IDynamicApiController, ITransient
Description = input.Description,
Attachment = input.Attachment,
GoodsTag = input.GoodsTag,
ExpireTime = DateTimeOffset.Now.AddMinutes(10),
ExpireTime = DateTimeOffset.UtcNow.AddMinutes(10),
NotifyUrl = _payCallBackOptions.WechatPayUrl,
Amount = new CreatePayTransactionJsapiRequest.Types.Amount() { Total = input.Total },
Payer = new CreatePayTransactionJsapiRequest.Types.Payer() { OpenId = input.OpenId }
@ -126,7 +126,7 @@ public class SysWechatPayService : IDynamicApiController, ITransient
[DisplayName("微信支付统一下单获取Id(服务商模式)")]
public async Task<CreatePayTransactionOutput> CreatePayPartnerTransaction([FromBody] WechatPayTransactionInput input)
{
string outTradeNumber = DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000); // 微信需要的订单号(唯一)
string outTradeNumber = DateTimeOffset.UtcNow.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000); // 微信需要的订单号(唯一)
//检查订单信息是否已存在(使用“商户交易单号+状态”唯一性判断)
var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OrderId == input.OrderId && u.OrderStatus == input.OrderStatus);
@ -145,7 +145,7 @@ public class SysWechatPayService : IDynamicApiController, ITransient
Description = input.Description,
Attachment = input.Attachment,
GoodsTag = input.GoodsTag,
ExpireTime = DateTimeOffset.Now.AddMinutes(10),
ExpireTime = DateTimeOffset.UtcNow.AddMinutes(10),
NotifyUrl = _payCallBackOptions.WechatPayUrl,
Amount = new CreatePayPartnerTransactionJsapiRequest.Types.Amount() { Total = input.Total },
Payer = new CreatePayPartnerTransactionJsapiRequest.Types.Payer() { OpenId = input.OpenId }
@ -288,7 +288,7 @@ public class SysWechatPayService : IDynamicApiController, ITransient
var request = new CreateRefundDomesticRefundRequest()
{
OutTradeNumber = input.OutTradeNumber,
OutRefundNumber = "REFUND_" + DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff"),
OutRefundNumber = "REFUND_" + DateTimeOffset.UtcNow.ToString("yyyyMMddHHmmssfff"),
Amount = new CreateRefundDomesticRefundRequest.Types.Amount()
{
Total = input.Total,

View File

@ -123,13 +123,13 @@ public class SysWxOpenService : IDynamicApiController, ITransient
[DisplayName("验证签名")]
public string VerifySignature([FromQuery] VerifySignatureInput input)
{
bool valid = _wechatApiClient.VerifyEventSignatureForEcho(input.timestamp, input.nonce, input.signature);
bool valid = _wechatApiClient.VerifyEventSignatureForEcho(input.Timestamp, input.Nonce, input.Signature);
if (!valid)
{
return "fail";
}
return input.echostr;
return input.Echostr;
}
/// <summary>

View File

@ -117,7 +117,7 @@ public static class SqlSugarSetup
// par.Value = string.Concat(par.Value.ToString()[..100], "......");
//}
var log = $"【{DateTime.Now}——执行SQL】\r\n{UtilMethods.GetNativeSql(sql, pars)}\r\n";
var log = $"【{DateTime.UtcNow}——执行SQL】\r\n{UtilMethods.GetNativeSql(sql, pars)}\r\n";
var originColor = Console.ForegroundColor;
if (sql.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase))
Console.ForegroundColor = ConsoleColor.Green;
@ -132,7 +132,7 @@ public static class SqlSugarSetup
db.Aop.OnError = ex =>
{
if (ex.Parametres == null) return;
var log = $"【{DateTime.Now}——错误SQL】\r\n{UtilMethods.GetNativeSql(ex.Sql, (SugarParameter[])ex.Parametres)}\r\n";
var log = $"【{DateTime.UtcNow}——错误SQL】\r\n{UtilMethods.GetNativeSql(ex.Sql, (SugarParameter[])ex.Parametres)}\r\n";
Log.Error(log, ex);
App.PrintToMiniProfiler("SqlSugar", "Error", log);
};
@ -152,7 +152,7 @@ public static class SqlSugarSetup
var fileName = db.Ado.SqlStackTrace.FirstFileName; // 文件名
var fileLine = db.Ado.SqlStackTrace.FirstLine; // 行号
var firstMethodName = db.Ado.SqlStackTrace.FirstMethodName; // 方法名
var log = $"【{DateTime.Now}——超时SQL】\r\n【所在文件名】{fileName}\r\n【代码行数】{fileLine}\r\n【方法名】{firstMethodName}\r\n" + $"【SQL语句】{UtilMethods.GetNativeSql(sql, pars)}";
var log = $"【{DateTime.UtcNow}——超时SQL】\r\n【所在文件名】{fileName}\r\n【代码行数】{fileLine}\r\n【方法名】{firstMethodName}\r\n" + $"【SQL语句】{UtilMethods.GetNativeSql(sql, pars)}";
Log.Warning(log);
App.PrintToMiniProfiler("SqlSugar", "Slow", log);
}
@ -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.Equals(DateTime.Parse("0001/1/1 0:00:00")))
entityInfo.SetValue(DateTime.UtcNow);
}
// 若当前用户非空web线程时
if (App.User != null)
@ -211,7 +213,7 @@ public static class SqlSugarSetup
else if (entityInfo.OperationType == DataFilterType.UpdateByObject)
{
if (entityInfo.PropertyName == nameof(EntityBase.UpdateTime))
entityInfo.SetValue(DateTime.Now);
entityInfo.SetValue(DateTime.UtcNow);
else if (entityInfo.PropertyName == nameof(EntityBase.UpdateUserId))
entityInfo.SetValue(App.User?.FindFirst(ClaimConst.UserId)?.Value);
else if (entityInfo.PropertyName == nameof(EntityBase.UpdateUserName))
@ -266,7 +268,7 @@ public static class SqlSugarSetup
var logDb = ITenant.IsAnyConnection(SqlSugarConst.LogConfigId) ? ITenant.GetConnectionScope(SqlSugarConst.LogConfigId) : db;
await logDb.CopyNew().Insertable(logDiff).ExecuteCommandAsync();
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(DateTime.Now + $"\r\n*****开始差异日志*****\r\n{Environment.NewLine}{JSON.Serialize(logDiff)}{Environment.NewLine}*****结束差异日志*****\r\n");
Console.WriteLine(DateTime.UtcNow + $"\r\n*****开始差异日志*****\r\n{Environment.NewLine}{JSON.Serialize(logDiff)}{Environment.NewLine}*****结束差异日志*****\r\n");
};
}

View File

@ -116,7 +116,7 @@ public class AdminResultProvider : IUnifyResultProvider
Result = data,
Type = succeeded ? "success" : "error",
Extras = UnifyContext.Take(),
Time = DateTime.Now
Time = DateTime.UtcNow
};
}
}

View File

@ -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),

View File

@ -198,19 +198,19 @@ public static class ComputerUtil
//返回1705379131
//使用date格式化即可
string output = ShellUtil.Bash("date -r $(sysctl -n kern.boottime | awk '{print $4}' | tr -d ',') +\"%Y-%m-%d %H:%M:%S\"").Trim();
runTime = DateTimeUtil.FormatTime((DateTime.Now - output.ParseToDateTime()).TotalMilliseconds.ToString().Split('.')[0].ParseToLong());
runTime = DateTimeUtil.FormatTime((DateTime.UtcNow - output.ParseToDateTime()).TotalMilliseconds.ToString().Split('.')[0].ParseToLong());
}
else if (IsUnix())
{
string output = ShellUtil.Bash("uptime -s").Trim();
runTime = DateTimeUtil.FormatTime((DateTime.Now - output.ParseToDateTime()).TotalMilliseconds.ToString().Split('.')[0].ParseToLong());
runTime = DateTimeUtil.FormatTime((DateTime.UtcNow - output.ParseToDateTime()).TotalMilliseconds.ToString().Split('.')[0].ParseToLong());
}
else
{
string output = ShellUtil.Cmd("wmic", "OS get LastBootUpTime/Value");
string[] outputArr = output.Split('=', (char)StringSplitOptions.RemoveEmptyEntries);
if (outputArr.Length == 2)
runTime = DateTimeUtil.FormatTime((DateTime.Now - outputArr[1].Split('.')[0].ParseToDateTime()).TotalMilliseconds.ToString().Split('.')[0].ParseToLong());
runTime = DateTimeUtil.FormatTime((DateTime.UtcNow - outputArr[1].Split('.')[0].ParseToDateTime()).TotalMilliseconds.ToString().Split('.')[0].ParseToLong());
}
return runTime;
}

View File

@ -17,9 +17,9 @@ public class DateTimeUtil
public static DateTime GetBeginTime(DateTime? dateTime, int days = 0)
{
if (dateTime == DateTime.MinValue || dateTime == null)
return DateTime.Now.AddDays(days);
return DateTime.UtcNow.AddDays(days);
return dateTime ?? DateTime.Now;
return dateTime ?? DateTime.UtcNow;
}
/// <summary>
@ -122,7 +122,7 @@ public class DateTimeUtil
{
if (dt == null) return string.Empty;
if (dt.Value.Year == DateTime.Now.Year)
if (dt.Value.Year == DateTime.UtcNow.Year)
return dt.Value.ToString("MM-dd HH:mm");
else
return dt.Value.ToString("yyyy-MM-dd HH:mm");

View File

@ -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>
/// 关键字查询

View File

@ -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();
}

View File

@ -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,7 +50,7 @@
</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}`" />
@ -58,7 +58,7 @@
</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')]" />
@ -163,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>
@ -334,7 +334,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
// 查询操作
const handleQuery = async (reset = false) => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
// 重置操作

View File

@ -117,9 +117,9 @@ public class ApprovalFlowService : IDynamicApiController, ITransient
/// <returns></returns>
private async Task<string> LastCode(string prefix)
{
var today = DateTime.Now.Date;
var today = DateTime.UtcNow.Date;
var count = await _approvalFlowRep.AsQueryable().Where(u => u.CreateTime >= today).CountAsync();
return prefix + DateTime.Now.ToString("yyMMdd") + string.Format("{0:d2}", count + 1);
return prefix + DateTime.UtcNow.ToString("yyMMdd") + string.Format("{0:d2}", count + 1);
}
[HttpGet]

View File

@ -48,7 +48,7 @@ public class SysApprovalService : ITransient
var approvalFlow = new ApprovalFlowRecord
{
FormName = funcName,
CreateTime = DateTime.Now,
CreateTime = DateTime.UtcNow,
};
// 判断是否需要审批
@ -59,7 +59,7 @@ public class SysApprovalService : ITransient
FlowId = approvalFlow.Id,
FormName = funcName,
FormType = typeName,
CreateTime = DateTime.Now,
CreateTime = DateTime.UtcNow,
};
// 判断是否需要审批

View File

@ -167,7 +167,7 @@ public class SyncDingTalkUserJob : IJob
var originColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine("【" + DateTime.Now + "】同步钉钉用户");
Console.WriteLine("【" + DateTime.UtcNow + "】同步钉钉用户");
Console.ForegroundColor = originColor;
}
}

View File

@ -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()

View File

@ -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.67",
"vxe-table": "^4.7.50",
"vxe-pc-ui": "^4.0.68",
"vxe-table": "^4.7.51",
"vxe-table-plugin-element": "^4.0.4",
"vxe-table-plugin-export-xlsx": "^4.0.5",
"xe-utils": "^3.5.28",

View File

@ -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';

View File

@ -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));
}
}

View File

@ -0,0 +1,476 @@
/* 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 { AdminResultListSysSchedule } from '../models';
import { AdminResultSysSchedule } from '../models';
import { DeleteScheduleInput } 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 {ScheduleInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysSchedulePagePost: async (body?: ScheduleInput, 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 {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 {ScheduleInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysSchedulePagePost(body?: ScheduleInput, 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 {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 {ScheduleInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysSchedulePagePost(body?: ScheduleInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysSchedule>> {
return SysScheduleApiFp(configuration).apiSysSchedulePagePost(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 {ScheduleInput} [body]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysScheduleApi
*/
public async apiSysSchedulePagePost(body?: ScheduleInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysSchedule>> {
return SysScheduleApiFp(this.configuration).apiSysSchedulePagePost(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));
}
}

View File

@ -200,19 +200,19 @@ export const SysWxOpenApiAxiosParamCreator = function (configuration?: Configura
}
if (signature !== undefined) {
localVarQueryParameter['signature'] = signature;
localVarQueryParameter['Signature'] = signature;
}
if (timestamp !== undefined) {
localVarQueryParameter['timestamp'] = timestamp;
localVarQueryParameter['Timestamp'] = timestamp;
}
if (nonce !== undefined) {
localVarQueryParameter['nonce'] = nonce;
localVarQueryParameter['Nonce'] = nonce;
}
if (echostr !== undefined) {
localVarQueryParameter['echostr'] = echostr;
localVarQueryParameter['Echostr'] = echostr;
}
const query = new URLSearchParams(localVarUrlObj.search);

View File

@ -0,0 +1,118 @@
/* 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 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
*/
content: string;
}

View File

@ -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;
/**
* successwarningerror
*
* @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;
}

View 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;
/**
* successwarningerror
*
* @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;
}

View 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;
}

View File

@ -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';
@ -276,6 +280,7 @@ 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';
@ -342,6 +347,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';
@ -374,6 +380,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';

View 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 ScheduleInput
*/
export interface ScheduleInput {
/**
* @type {Date}
* @memberof ScheduleInput
*/
startTime?: Date | null;
/**
* @type {Date}
* @memberof ScheduleInput
*/
endTime?: Date | null;
}

View File

@ -0,0 +1,118 @@
/* 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 SysSchedule
*/
export interface SysSchedule {
/**
* Id
*
* @type {number}
* @memberof SysSchedule
*/
id?: number;
/**
*
*
* @type {Date}
* @memberof SysSchedule
*/
createTime?: Date;
/**
*
*
* @type {Date}
* @memberof SysSchedule
*/
updateTime?: Date | null;
/**
* Id
*
* @type {number}
* @memberof SysSchedule
*/
createUserId?: number | null;
/**
*
*
* @type {string}
* @memberof SysSchedule
*/
createUserName?: string | null;
/**
* Id
*
* @type {number}
* @memberof SysSchedule
*/
updateUserId?: number | null;
/**
*
*
* @type {string}
* @memberof SysSchedule
*/
updateUserName?: string | null;
/**
*
*
* @type {boolean}
* @memberof SysSchedule
*/
isDelete?: boolean;
/**
* Id
*
* @type {number}
* @memberof SysSchedule
*/
tenantId?: number | null;
/**
* Id
*
* @type {number}
* @memberof SysSchedule
*/
userId?: number;
/**
*
*
* @type {Date}
* @memberof SysSchedule
*/
scheduleTime?: Date | null;
/**
*
*
* @type {string}
* @memberof SysSchedule
*/
content: string;
}

View File

@ -0,0 +1,118 @@
/* 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 UpdateScheduleInput
*/
export interface UpdateScheduleInput {
/**
* Id
*
* @type {number}
* @memberof UpdateScheduleInput
*/
id?: number;
/**
*
*
* @type {Date}
* @memberof UpdateScheduleInput
*/
createTime?: Date;
/**
*
*
* @type {Date}
* @memberof UpdateScheduleInput
*/
updateTime?: Date | null;
/**
* Id
*
* @type {number}
* @memberof UpdateScheduleInput
*/
createUserId?: number | null;
/**
*
*
* @type {string}
* @memberof UpdateScheduleInput
*/
createUserName?: string | null;
/**
* Id
*
* @type {number}
* @memberof UpdateScheduleInput
*/
updateUserId?: number | null;
/**
*
*
* @type {string}
* @memberof UpdateScheduleInput
*/
updateUserName?: string | null;
/**
*
*
* @type {boolean}
* @memberof UpdateScheduleInput
*/
isDelete?: boolean;
/**
* Id
*
* @type {number}
* @memberof UpdateScheduleInput
*/
tenantId?: number | null;
/**
* Id
*
* @type {number}
* @memberof UpdateScheduleInput
*/
userId?: number;
/**
*
*
* @type {Date}
* @memberof UpdateScheduleInput
*/
scheduleTime?: Date | null;
/**
*
*
* @type {string}
* @memberof UpdateScheduleInput
*/
content: string;
}

View File

@ -132,16 +132,12 @@ export const useUserInfo = defineStore('userInfo', {
// 根据字典类型和代码取字典项
getDictItemByCode(typePCode: string, val: string) {
if (val != undefined) {
val = val.toString();
if (val) {
const _val = val.toString();
const ds = this.getDictDatasByCode(typePCode);
for (let index = 0; index < ds.length; index++) {
const element = ds[index];
if (element.code == _val) {
return element;
}
if (val != undefined && val !== '') {
const _val = val.toString();
const ds = this.getDictDatasByCode(typePCode);
for (const element of ds) {
if (element.code === _val) {
return element;
}
}
}
@ -150,12 +146,11 @@ export const useUserInfo = defineStore('userInfo', {
// 根据字典类型和值取描述
getDictLabelByVal(typePCode: string, val: string) {
if (val) {
if (val != undefined && val !== '') {
const _val = val.toString();
const ds = this.getDictDatasByCode(typePCode);
for (let index = 0; index < ds.length; index++) {
const element = ds[index];
if (element.value == _val) {
for (const element of ds) {
if (element.value === _val) {
return element;
}
}
@ -167,12 +162,12 @@ export const useUserInfo = defineStore('userInfo', {
getDictValByLabel(typePCode: string, label: string) {
if (!label) return '';
const ds = this.getDictDatasByCode(typePCode);
for (let index = 0; index < ds.length; index++) {
const element = ds[index];
if (element.name == label) {
for (const element of ds) {
if (element.name === label) {
return element;
}
}
return ''; // 明确返回空字符串
},
// 根据字典类型获取字典数据
@ -182,18 +177,20 @@ export const useUserInfo = defineStore('userInfo', {
// 根据字典类型获取字典数据(值转为数字类型)
getDictIntDatasByCode(dictTypeCode: string) {
var ds = this.dictListInt[dictTypeCode];
let ds = this.dictListInt[dictTypeCode];
if (ds) {
return ds;
} else {
ds = this.dictList[dictTypeCode].map((element: { code: any }) => {
var d = { ...element };
d.code = element.code - 0;
return d;
}
const dictList = this.dictList[dictTypeCode];
if (dictList) {
ds = dictList.map((element: { code: any }) => {
return { ...element, code: Number(element.code) };
});
this.dictListInt[dictTypeCode] = ds;
return ds;
}
return ds;
},
},
});

678
Web/src/utils/calendar.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
<template>
<div class="notice-container" v-loading="options.loading">
<div class="notice-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">

View File

@ -32,5 +32,6 @@ export default {
color: #999;
margin-top: 10px;
line-height: 1.8;
/* height: 100px; */
}
</style>

View File

@ -1,7 +1,9 @@
<template>
<el-card shadow="hover" header="更新记录">
<template #header>
<el-button type="primary" icon="ele-Refresh" round @click="refresh">更新记录</el-button>
<el-icon style="display: inline; vertical-align: middle"> <ele-DocumentCopy /> </el-icon>
<span style=""> 更新记录 </span>
<el-button type="primary" icon="ele-Refresh" round plain @click="refresh" style="float: right">更新记录</el-button>
</template>
<div class="commit" v-loading="state.loading">
<el-timeline style="max-width: 600px" v-if="state.list.length > 0">

View File

@ -4,6 +4,9 @@ type Component = any;
const resultComps: Record<string, Component> = {};
// 要排除的组件名称数组
const excludeComponents = ['scheduleEdit'];
// 使用 import.meta.glob 动态导入当前目录中的所有 .vue 文件,急切导入
const requireComponent = import.meta.glob('./*.vue', { eager: true });
// console.log(requireComponent);
@ -11,12 +14,18 @@ const requireComponent = import.meta.glob('./*.vue', { eager: true });
Object.keys(requireComponent).forEach((fileName: string) => {
// 处理文件名,去掉开头的 './' 和结尾的文件扩展名
const componentName = fileName.replace(/^\.\/(.*)\.\w+$/, '$1');
// 如果组件名称在排除数组中,跳过导入
if (excludeComponents.includes(componentName)) {
return;
}
// 确保模块导出存在并且是默认导出
const componentModule = requireComponent[fileName] as { default: Component };
// 将组件添加到 resultComps 中,使用处理后的文件名作为键
resultComps[componentName] = componentModule.default;
});
// 动态的这里拿到title等东西是为了这里显示
// 标记 resultComps 为原始对象,避免其被设为响应式
export default markRaw(resultComps);

View File

@ -0,0 +1,247 @@
<template>
<el-card shadow="hover" header="我的日程" class="item-background">
<template #header>
<el-icon style="display: inline; vertical-align: middle"> <ele-Calendar /> </el-icon>
<span style=""> 我的日程 </span>
<el-button type="primary" icon="ele-CirclePlus" round plain @click="openAddSchedule" style="float: right">添加日程</el-button>
</template>
<div class="custome-canlendar">
<el-calendar v-model="state.calendarValue">
<template #date-cell="{ data }">
<div @click="handleClickDate(data)">
<div class="spandate">{{ data.day.split('-').slice(2).join('-') }}</div>
<div v-for="(item, key) in state.ScheduleData" :key="key">
<el-badge v-if="FormatDate(data.day) == FormatDate(item.scheduleTime)" is-dot class="item"></el-badge>
</div>
</div>
<div style="font-size: 10px">
{{ solarDate2lunar(data.day) }}
</div>
</template>
</el-calendar>
</div>
<div class="schedule-list">
<div class="item" v-for="(item, index) in state.TodayScheduleData" :key="index" @click="openEditSchedule(item)">
<el-icon style="display: inline; vertical-align: middle"> <ele-Calendar /> </el-icon>
<span class="content" style="padding-left: 10px">
<span>
{{ item.scheduleTime }}
</span>
<span style="padding-left: 15px; font-weight: 600; color: var(--el-color-primary)">
{{ item.content }}
</span>
</span>
</div>
</div>
<EditSchedule ref="editScheduleRef" :title="state.editTitle" @handleQuery="handleQuery"> </EditSchedule>
</el-card>
</template>
<script lang="ts">
export default {
title: '日程',
icon: 'ele-Odometer',
description: '日程演示',
};
</script>
<script setup lang="ts">
import { reactive, onMounted, ref } from 'vue';
import { dayjs } from 'element-plus';
import calendar from '/@/utils/calendar.js';
import EditSchedule from '/@/views/home/widgets/components/scheduleEdit.vue';
import { getAPI } from '/@/utils/axios-utils';
import { SysScheduleApi } from '/@/api-services/api';
import { SysSchedule } from '/@/api-services/models';
const editScheduleRef = ref<InstanceType<typeof EditSchedule>>();
const state = reactive({
ScheduleData: [] as Array<SysSchedule>, //
TodayScheduleData: [] as Array<SysSchedule>, //
calendarValue: new Date(),
queryParams: {
startTime: new Date(),
endTime: new Date(),
},
editTitle: '',
});
//
onMounted(async () => {
await handleQuery();
});
//
const handleQuery = async () => {
debugger;
state.queryParams.startTime = GetMonthFirstDay(state.calendarValue);
state.queryParams.endTime = GetMonthLastDay(state.calendarValue);
let params = Object.assign(state.queryParams);
var res = await getAPI(SysScheduleApi).apiSysSchedulePagePost(params);
state.ScheduleData = res.data.result ?? [];
if (state.ScheduleData.length > 0) {
state.TodayScheduleData = state.ScheduleData.filter((item) => {
return FormatDate(item.scheduleTime) == FormatDate(state.calendarValue);
});
}
};
//
const solarDate2lunar = (solarDate: any) => {
var solar = solarDate.split('-');
var lunar = calendar.solar2lunar(solar[0], solar[1], solar[2]);
// return solar[1] + '-' + solar[2] + '\n' + lunar.IMonthCn + lunar.IDayCn;
return lunar.IMonthCn + lunar.IDayCn;
};
//
const handleQueryByDate = async (date: any) => {
state.queryParams.startTime = FormatDateDelHMS(date);
state.queryParams.endTime = FormatDateEndHMS(date);
let params = Object.assign(state.queryParams);
var res = await getAPI(SysScheduleApi).apiSysSchedulePagePost(params);
state.TodayScheduleData = res.data.result ?? [];
};
//
const openAddSchedule = () => {
state.editTitle = '添加日程';
editScheduleRef.value?.openDialog({ id: undefined, status: 1, orderNo: 100 });
};
//
const openEditSchedule = async (row: any) => {
state.editTitle = '编辑日程';
editScheduleRef.value?.openDialog(row, true);
};
//
async function handleClickDate(data: any) {
await handleQueryByDate(data.day);
}
function GetMonthFirstDay(date: any) {
var newDate = new Date(date);
newDate.setDate(1);
newDate.setHours(0);
newDate.setMinutes(0);
newDate.setSeconds(0);
return newDate;
}
function GetMonthLastDay(date: any) {
var newDate = new Date(date);
newDate.setMonth(newDate.getMonth() + 1);
newDate.setDate(0);
newDate.setHours(0);
newDate.setMinutes(0);
newDate.setSeconds(0);
return newDate;
}
//
function FormatDateDelHMS(date: any) {
var newDate = new Date(date);
newDate.setHours(0);
newDate.setMinutes(0);
newDate.setSeconds(0);
return newDate;
}
function FormatDateEndHMS(date: any) {
var newDate = new Date(date);
newDate.setHours(23);
newDate.setMinutes(59);
newDate.setSeconds(59);
return newDate;
}
//
function FormatDate(date: any) {
return dayjs(date).format('YYYY-MM-DD');
}
</script>
<style lang="scss" scoped>
.custome-canlendar {
position: relative;
text-align: center;
:deep(.el-calendar) {
.el-calendar-table .el-calendar-day {
width: 100%;
height: 100%;
}
.el-calendar__body {
padding: 5px 0;
}
.el-calendar-table .el-calendar-day {
position: relative;
}
td .spandate {
margin: auto;
width: 26px;
height: 26px;
line-height: 26px;
border-radius: 50%;
}
td.is-selected .spandate {
width: 26px;
height: 26px;
line-height: 26px;
border-radius: 50%;
color: #fff;
background-color: var(--el-color-primary);
}
/*小红点样式*/
.el-badge {
position: absolute;
left: 0;
bottom: -8px;
width: 100%;
}
}
}
//
.schedule-list {
overflow-y: auto;
height: 150px;
.item {
position: relative;
margin-bottom: 5px;
padding: 0 11px;
line-height: 24px;
background-color: #f1f1f1;
cursor: pointer;
&::before {
position: absolute;
left: 0;
top: 0;
height: 100%;
content: '';
width: 3px;
background: var(--el-color-primary);
}
.date {
margin-right: 5px;
font-size: 14px;
}
.content {
color: #666;
font-size: 14px;
}
}
}
</style>

View File

@ -0,0 +1,111 @@
<template>
<div class="editSchedule-container">
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="700px">
<template #header>
<div style="color: #fff">
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
<span> {{ props.title }} </span>
</div>
</template>
<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto">
<el-row :gutter="35">
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="日程时间" prop="scheduleTime" :rules="[{ required: true, message: '日程时间不能为空', trigger: 'blur' }]">
<el-date-picker v-model="state.ruleForm.scheduleTime" type="datetime" placeholder="请选择日程时间" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" class="w100" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="日程内容" prop="content" :rules="[{ required: true, message: '内容内容不能为空', trigger: 'blur' }]">
<el-input v-model="state.ruleForm.content" placeholder="内容内容" clearable type="textarea" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button v-if="state.showRemove" @click="remove">删除</el-button>
<el-button @click="cancel"> </el-button>
<el-button type="primary" @click="submit"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup name="editSchedule">
import { onMounted, reactive, ref } from 'vue';
import { dayjs, ElMessageBox, ElMessage, ElNotification } from 'element-plus';
import { getAPI } from '/@/utils/axios-utils';
import { SysScheduleApi } from '/@/api-services/api';
import { SysSchedule, UpdateScheduleInput } from '/@/api-services/models';
const props = defineProps({
title: String,
userScheduleData: Array<SysSchedule>,
});
const emits = defineEmits(['handleQuery']);
const ruleFormRef = ref();
const state = reactive({
isShowDialog: false,
showRemove: false,
ruleForm: {} as any,
});
//
onMounted(async () => {});
//
const openDialog = (row: any, showRemove: boolean = false) => {
ruleFormRef.value?.resetFields();
state.showRemove = showRemove;
state.ruleForm = JSON.parse(JSON.stringify(row));
state.ruleForm.scheduleTime = dayjs(state.ruleForm.scheduleTime ?? new Date()).format('YYYY-MM-DD HH:mm:ss');
state.isShowDialog = true;
};
//
const closeDialog = () => {
emits('handleQuery', true);
state.isShowDialog = false;
};
//
const cancel = () => {
state.isShowDialog = false;
};
//
const submit = () => {
console.log(JSON.stringify(state.ruleForm));
ruleFormRef.value.validate(async (valid: boolean) => {
if (!valid) return;
if (state.ruleForm.id != undefined && state.ruleForm.id > 0) {
await getAPI(SysScheduleApi).apiSysScheduleUpdatePost(state.ruleForm);
} else {
await getAPI(SysScheduleApi).apiSysScheduleAddPost(state.ruleForm);
}
closeDialog();
});
};
//
const remove = () => {
ElMessageBox.confirm(`确定删除吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
await getAPI(SysScheduleApi).apiSysScheduleDeletePost(state.ruleForm);
closeDialog();
ElMessage.success('操作成功');
})
.catch(() => {});
};
//
defineExpose({ openDialog });
</script>

View File

@ -19,7 +19,7 @@ export default {
};
</script>
<script setup lang="ts" name="timeing">
<script setup lang="ts" name="timer">
import { formatDate } from '/@/utils/formatTime';
import { ref, onMounted, onUnmounted } from 'vue';
const time = ref<string>('');

View File

@ -7,11 +7,11 @@
<div style="height: 210px; text-align: center">
<img :src="verSvg" style="height: 140px" />
<h2 style="margin-top: 15px">Admin.NET</h2>
<p style="margin-top: 5px">最新版本 {{ ver }}</p>
<p style="margin-top: 5px">最新版本 {{ version }}</p>
</div>
<div style="margin-top: 20px">
<el-button type="primary" plain round @click="golog">更新日志</el-button>
<el-button type="primary" plain round @click="gogit">gitee</el-button>
<div style="margin-top: 20px; margin-bottom: 20px; float: right">
<el-button type="primary" icon="ele-DocumentCopy" plain round @click="golog">更新日志</el-button>
<el-button type="primary" icon="ele-Eleme" plain round @click="gogit">gitee</el-button>
</div>
</el-card>
</template>
@ -24,18 +24,18 @@ export default {
};
</script>
<script setup lang="ts" name="ver">
<script setup lang="ts" name="version">
import { ref, onMounted } from 'vue';
import verSvg from '/@/assets/img/ver.svg';
const ver = ref<string>('loading...');
const version = ref<string>('loading...');
onMounted(() => {
ver.value = 'v2.0.0';
version.value = 'v2.0.0';
});
const getVer = () => {
ver.value = 'v2.0.0';
version.value = 'v2.0.0';
};
const golog = () => {

View File

@ -13,7 +13,7 @@
<div v-if="nowCompsList.length <= 0" class="no-widgets">
<el-empty description="没有部件啦" :image-size="300"></el-empty>
</div>
<el-row :gutter="15">
<el-row :gutter="8">
<el-col v-for="(item, index) in grid.layout" :key="index" :md="item" :xs="24">
<draggable
v-model="grid.copmsList[index]"
@ -27,12 +27,12 @@
class="draggable-box"
>
<template #item="{ element }">
<div class="widgets-item mb15">
<div class="widgets-item mb8">
<component :is="allComps[element]"></component>
<div v-if="customizing" class="customize-overlay">
<el-button class="close" type="danger" plain icon="ele-Close" @click="remove(element)"></el-button>
<label>
<el-icon><component :is="allComps[element].icon" /></el-icon>{{ allComps[element].title }}
<label v-if="allComps[element]">
<el-icon> <component :is="allComps[element].icon" /> </el-icon>{{ allComps[element].title }}
</label>
</div>
</div>
@ -43,6 +43,7 @@
</div>
</div>
</div>
<div v-if="customizing" class="widgets-aside">
<div class="widgets-top">
<div class="widgets-aside-title">
@ -111,7 +112,9 @@
</div>
<div v-for="item in myCompsList" :key="item.title" class="widgets-list-item">
<div class="item-logo">
<el-icon><component :is="item.icon" /></el-icon>
<el-icon>
<component :is="item.icon" />
</el-icon>
</div>
<div class="item-info">
<h2>{{ item.title }}</h2>
@ -132,7 +135,7 @@
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted, nextTick } from 'vue';
import { ref, computed, onMounted, nextTick } from 'vue';
import draggable from 'vuedraggable';
import { clone } from '/@/utils/arrayOperation';
import allComps from './components/index';
@ -146,8 +149,8 @@ const defaultGrid = {
layout: [12, 6, 6],
copmsList: [
['welcome', 'commit'],
['about', 'ver'],
['timeing', 'progressing'],
['about', 'version'],
['timer', 'schedule'],
],
};
@ -182,7 +185,7 @@ const availableCompsList = computed(() => {
});
const myCompsList = computed(() => {
const myGrid = Local.get('DASHBOARDGRID') || ['welcome', 'myapp', 'ver', 'timeing', 'progressing', 'echarts', 'about', 'commit'];
const myGrid = Local.get('DASHBOARDGRID') || ['welcome', 'myapp', 'version', 'timer', 'echarts', 'about', 'commit', 'schedule'];
return availableCompsList.value.filter((comp) => !comp.disabled && myGrid.includes(comp.key));
});
@ -255,7 +258,7 @@ const close = () => {
flex: 1;
overflow: auto;
overflow-x: hidden;
padding: 10px;
padding: 4px;
}
.widgets-aside {
width: 360px;
@ -292,7 +295,7 @@ const close = () => {
}
.widgets-top {
margin-bottom: 15px;
margin-bottom: 8px;
display: flex;
justify-content: space-between;
align-items: center;

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-codeGen-container" v-loading="options.loading">
<div class="sys-codeGen-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -161,7 +161,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-config-container" v-loading="options.loading">
<div class="sys-config-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -148,7 +148,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
// vxe-gridcommitProxy(query)
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-database-container" v-loading="options.loading">
<div class="sys-database-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -169,7 +169,9 @@ const handleQueryColumnApi = async () => {
//
const handleQueryColumn = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-file-container" v-loading="options.loading">
<div class="sys-file-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -223,7 +223,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-job-container" v-loading="options.loading">
<div class="sys-job-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">

View File

@ -111,7 +111,7 @@ const state = reactive({
},
localPageParam: {
pageSize: 50 as number,
defaultSort: { field: 'orderNo', order: 'asc', descStr: 'desc' },
defaultSort: { field: 'id', order: 'asc', descStr: 'desc' },
},
visible: false,
title: '',
@ -165,7 +165,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-difflog-container" v-loading="options.loading">
<div class="sys-difflog-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -118,7 +118,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-exlog-container" v-loading="options.loading">
<div class="sys-exlog-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -191,7 +191,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-oplog-container" v-loading="options.loading">
<div class="sys-oplog-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -193,7 +193,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-vislog-container" v-loading="options.loading">
<div class="sys-vislog-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -143,7 +143,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-menu-container" v-loading="options.loading">
<div class="sys-menu-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -144,7 +144,9 @@ const handleQueryApi = async () => {
//
const handleQuery = async () => {
// vxe-gridcommitProxy(query)
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-notice-container" v-loading="options.loading">
<div class="sys-notice-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -147,7 +147,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sysOAuthUser-container" v-loading="options.loading">
<div class="sysOAuthUser-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -147,7 +147,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -179,7 +179,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-open-access-container" v-loading="options.loading">
<div class="sys-open-access-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -134,7 +134,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-org-container" v-loading="options.loading">
<div class="sys-org-container">
<el-row :gutter="5" style="width: 100%; height: 100%">
<el-col :span="4" :xs="24" style="display: flex; height: 100%">
<OrgTree ref="orgTreeRef" @node-click="handleNodeChange" />

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-plugin-container" v-loading="options.loading">
<div class="sys-plugin-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -128,7 +128,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-pos-container" v-loading="options.loading">
<div class="sys-pos-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -134,7 +134,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
// vxe-gridcommitProxy(query)
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-print-container" v-loading="options.loading">
<div class="sys-print-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -130,7 +130,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-region-container" v-loading="options.loading">
<div class="sys-region-container">
<el-row :gutter="5" style="width: 100%; height: 100%">
<el-col :span="6" :xs="24" style="display: flex; height: 100%">
<RegionTree ref="regionTreeRef" @node-click="handleNodeChange" />
@ -119,6 +119,8 @@ const options = useVxeTable<SysRegion>(
},
// vxeGrid()vxe-table
{
stripe: false,
checkboxConfig: { range: false },
//
proxyConfig: { autoLoad: true, ajax: { query: ({ page, sort }) => handleQueryApi(page, sort) } },
//
@ -150,7 +152,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-role-container" v-loading="options.loading">
<div class="sys-role-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -155,7 +155,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-tenant-container" v-loading="options.loading">
<div class="sys-tenant-container">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', 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%">
<el-row :gutter="10">
@ -184,7 +184,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//

View File

@ -1,5 +1,5 @@
<template>
<div class="sys-user-container" v-loading="options.loading">
<div class="sys-user-container">
<el-row :gutter="5" style="width: 100%; height: 100%">
<el-col :span="4" :xs="24" style="display: flex; height: 100%">
<OrgTree ref="treeRef" @node-click="handleNodeChange" />
@ -184,7 +184,9 @@ const handleQueryApi = async (page: VxeGridPropTypes.ProxyAjaxQueryPageParams, s
//
const handleQuery = async () => {
options.loading = true;
await xGrid.value?.commitProxy('query');
options.loading = false;
};
//