diff --git a/Src/Dlhis.Basic/Dlhis.Basic.csproj b/Src/Dlhis.Basic/Dlhis.Basic.csproj index 2dac3683..2d3bb2ea 100644 --- a/Src/Dlhis.Basic/Dlhis.Basic.csproj +++ b/Src/Dlhis.Basic/Dlhis.Basic.csproj @@ -18,7 +18,7 @@ - + diff --git a/Src/Dlhis.Basic/MealUser/Services/Implements/MealUserService.cs b/Src/Dlhis.Basic/MealUser/Services/Implements/MealUserService.cs index 7c6d1b27..abb698f6 100644 --- a/Src/Dlhis.Basic/MealUser/Services/Implements/MealUserService.cs +++ b/Src/Dlhis.Basic/MealUser/Services/Implements/MealUserService.cs @@ -45,7 +45,7 @@ public class MealUserService : IMealUserService UserNo = request.UserNo, UserType = request.UserType, UserCode = gainfoEntity.Code, - CarNo = gainfoEntity.CarNo, + CarNo = gainfoEntity.CardNo, Balance = 0, BalanceOfRecharge = 0, BalanceOfSubsidies = 0, diff --git a/Src/Dlhis.Basic/Organization/Controllers/GainfosController.cs b/Src/Dlhis.Basic/Organization/Controllers/GainfosController.cs index 825e05ce..c18beb24 100644 --- a/Src/Dlhis.Basic/Organization/Controllers/GainfosController.cs +++ b/Src/Dlhis.Basic/Organization/Controllers/GainfosController.cs @@ -1,4 +1,6 @@ -using Dlhis.Basic.Organization.Request; +using System.ComponentModel.DataAnnotations; +using Dlhis.Basic.Organization.Filters; +using Dlhis.Basic.Organization.Request; using Dlhis.Basic.Organization.Response; using Dlhis.Basic.Organization.Services; using Kurisu.AspNetCore.MVC; @@ -96,7 +98,20 @@ public class GainfosController : ControllerBase [HttpPost("face")] public async Task UploadFaceAsync(GainfoUploadFaceRequest request) { - await _gainfoService.UploadFaceAsync(request); + await _gainfoService.UploadFaceAsync(request); + } + + /// + /// 获取人脸照片 + /// + /// + /// + [NotFound] + [AllowAnonymous] + [HttpGet("face")] + public async Task GetFaceAsync(string token) + { + return await _gainfoService.GetFaceAsync(token); } } diff --git a/Src/Dlhis.Basic/Organization/Filters/NotFoundAttribute.cs b/Src/Dlhis.Basic/Organization/Filters/NotFoundAttribute.cs new file mode 100644 index 00000000..b622d7cb --- /dev/null +++ b/Src/Dlhis.Basic/Organization/Filters/NotFoundAttribute.cs @@ -0,0 +1,30 @@ +using Kurisu.Core.Result; +using Kurisu.Core.Result.Abstractions; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace Dlhis.Basic.Organization.Filters; + +[AttributeUsage(AttributeTargets.Method)] +public class NotFoundAttribute : Attribute, IAsyncResultFilter +{ + public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) + { + if (context.Result is ObjectResult result) + { + var type = result.Value?.GetType(); + if (type.IsGenericType && type.IsAssignableTo(typeof(IApiResult))) + { + var apiResult = result.Value as DefaultApiResult; + + if (apiResult.Data is ProblemDetails _) + { + context.Result = new NotFoundResult(); + //context.HttpContext.Response + } + } + } + + await next(); + } +} diff --git a/Src/Dlhis.Basic/Organization/Services/IGainfoService.cs b/Src/Dlhis.Basic/Organization/Services/IGainfoService.cs index 416b7673..eff29b50 100644 --- a/Src/Dlhis.Basic/Organization/Services/IGainfoService.cs +++ b/Src/Dlhis.Basic/Organization/Services/IGainfoService.cs @@ -1,6 +1,7 @@ using Dlhis.Basic.Organization.Request; using Dlhis.Basic.Organization.Response; using Kurisu.Core.DataAccess.Dto; +using Microsoft.AspNetCore.Mvc; namespace Dlhis.Basic.Organization.Services; @@ -8,7 +9,6 @@ public interface IGainfoService : IScopeDependency { Task> GetPageAsync(GainfoPageRequest request); - Task SaveAsync(List requests); Task UpdateAsync(GainfoSaveRequest request); @@ -19,6 +19,7 @@ public interface IGainfoService : IScopeDependency Task CurrentUserInfoAsync(); - Task UploadFaceAsync(GainfoUploadFaceRequest request); + + Task GetFaceAsync(string token); } diff --git a/Src/Dlhis.Basic/Organization/Services/Implements/GainfoService.cs b/Src/Dlhis.Basic/Organization/Services/Implements/GainfoService.cs index 9eb3dd23..16c3c30a 100644 --- a/Src/Dlhis.Basic/Organization/Services/Implements/GainfoService.cs +++ b/Src/Dlhis.Basic/Organization/Services/Implements/GainfoService.cs @@ -1,5 +1,4 @@ -using System.Configuration; -using Dlhis.Basic.Organization.Request; +using Dlhis.Basic.Organization.Request; using Dlhis.Basic.Organization.Response; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Basic.Enums; @@ -12,6 +11,8 @@ using Kurisu.SqlSugar.Attributes; using Kurisu.SqlSugar.Extensions; using Kurisu.SqlSugar.Services; using Mapster; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Mvc; namespace Dlhis.Basic.Organization.Services.Implements; @@ -225,4 +226,44 @@ public class GainfoService : IGainfoService } }); } + + public async Task GetFaceAsync(string token) + { + return await Scoped.Request.Value.CreateAsync(async (sp) => + { + var timeLimitedDataProtector = sp.GetService() + .CreateProtector("down:face") + .ToTimeLimitedDataProtector(); + + try + { + var password = timeLimitedDataProtector.Unprotect(token); + var userCode = password.Split(':')[1]; + + var configuration = sp.GetService(); + var faceConnectionString = configuration.GetSection("SqlSugarOptions:FaceConnectionString").Value; + if (faceConnectionString.IsEmpty()) + { + throw new UserFriendlyException("暂不支持获取人脸"); + } + + var dbContext = sp.GetService(); + //todo 切换连接字符串 + dbContext.Client.CurrentConnectionConfig.ConnectionString = faceConnectionString; + var face = await dbContext.Queryable().Where(x => x.UserCode == userCode).SingleAsync(); + + if (face == null) + { + return new NotFoundResult(); + } + + return new FileContentResult(Convert.FromBase64String(face.Face), "image/png"); + + } + catch (Exception) + { + return new NotFoundResult(); + } + }); + } } diff --git a/Src/Dlhis.Basic/SqlSugarPack.cs b/Src/Dlhis.Basic/Packs/SqlSugarPack.cs similarity index 93% rename from Src/Dlhis.Basic/SqlSugarPack.cs rename to Src/Dlhis.Basic/Packs/SqlSugarPack.cs index 19fdbfbe..60895fd4 100644 --- a/Src/Dlhis.Basic/SqlSugarPack.cs +++ b/Src/Dlhis.Basic/Packs/SqlSugarPack.cs @@ -1,10 +1,9 @@ -using Dlhis.Entity.Basic.Entity; -using Kurisu.AspNetCore; +using Kurisu.AspNetCore; using Kurisu.AspNetCore.Startup; using Kurisu.SqlSugar.Extensions; using SqlSugar; -namespace Dlhis.Canteen; +namespace Dlhis.Basic.Packs; public class SqlSugarPack : BaseAppPack { diff --git a/Src/Dlhis.Basic/Program.cs b/Src/Dlhis.Basic/Program.cs index d7c99860..1f893a8b 100644 --- a/Src/Dlhis.Basic/Program.cs +++ b/Src/Dlhis.Basic/Program.cs @@ -1,6 +1,7 @@ using Kurisu.AspNetCore.Startup; using Kurisu.Startup; -using Microsoft.IdentityModel.Logging; +using Microsoft.AspNetCore.DataProtection; +using StackExchange.Redis; class Program { @@ -14,6 +15,17 @@ public class Startup : DefaultStartup { public Startup(IConfiguration configuration) : base(configuration) { - IdentityModelEventSource.ShowPII = true; + + } + + public override void ConfigureServices(IServiceCollection services) + { + base.ConfigureServices(services); + + //todo + var redis = ConnectionMultiplexer.Connect($"192.168.199.30:30115,defaultDatabase:1,password=zxc111"); + services.AddDataProtection() + .SetApplicationName("basic") + .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys"); } } \ No newline at end of file diff --git a/Src/Dlhis.Canteen/Order/Filters/CheckUserDeviceConsumeAttribute.cs b/Src/Dlhis.Canteen/Order/Filters/CheckUserDeviceConsumeAttribute.cs new file mode 100644 index 00000000..8f8cd8a8 --- /dev/null +++ b/Src/Dlhis.Canteen/Order/Filters/CheckUserDeviceConsumeAttribute.cs @@ -0,0 +1,14 @@ +//using Microsoft.AspNetCore.Mvc.Filters; + +//namespace Dlhis.Canteen.Order.Filters; + +///// +///// 检查用户设备消费 +///// +//public class CheckUserDeviceConsumeAttribute : IAsyncActionFilter +//{ +// public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) +// { + +// } +//} diff --git a/Src/Dlhis.Entity/Basic/Entity/GainfoEntity.cs b/Src/Dlhis.Entity/Basic/Entity/GainfoEntity.cs index 961b187e..788d3080 100644 --- a/Src/Dlhis.Entity/Basic/Entity/GainfoEntity.cs +++ b/Src/Dlhis.Entity/Basic/Entity/GainfoEntity.cs @@ -129,7 +129,7 @@ public class GainfoEntity : SugarBaseEntity /// 卡号 /// [SugarColumn(ColumnDescription = "卡号")] - public string CarNo { get; set; } + public string CardNo { get; set; } /// /// 备注 diff --git a/Src/Dlhis.Entity/Device/Entities/DeviceTask.cs b/Src/Dlhis.Entity/Device/Entities/DeviceTask.cs index cb56f36c..2185c284 100644 --- a/Src/Dlhis.Entity/Device/Entities/DeviceTask.cs +++ b/Src/Dlhis.Entity/Device/Entities/DeviceTask.cs @@ -10,7 +10,7 @@ namespace Dlhis.Entity.Device.Entities; /// 设备任务表 /// [SugarTable(TableName = "DeviceTask")] -public class DeviceTaskEntity : SugarBaseEntity, ITenantId +public class DeviceTaskEntity : SugarBaseEntity, ITenantId, IVersion { /// /// 任务类型 @@ -28,11 +28,6 @@ public class DeviceTaskEntity : SugarBaseEntity, ITenantId /// public string UserCode { get; set; } - /// - /// 用户名 - /// - public string UserName { get; set; } - /// /// 设备唯一号 /// @@ -49,6 +44,12 @@ public class DeviceTaskEntity : SugarBaseEntity, ITenantId [SugarColumn(ColumnDataType = "varchar(50)", SqlParameterDbType = typeof(EnumToStringConvert))] public DeviceTaskStatusEnumType Status { get; set; } + /// + /// 数据版本 + /// + public int Version { get; set; } + + /// /// 处理结果 /// diff --git a/Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj b/Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj index 1ea33e79..1a49f048 100644 --- a/Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj +++ b/Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj @@ -21,6 +21,7 @@ + diff --git a/Src/Dlhis.ScheduledTask/Program.cs b/Src/Dlhis.ScheduledTask/Program.cs index 281db99e..a4040c1c 100644 --- a/Src/Dlhis.ScheduledTask/Program.cs +++ b/Src/Dlhis.ScheduledTask/Program.cs @@ -1,6 +1,7 @@ using Kurisu.AspNetCore.Startup; using Kurisu.Startup; - +using Microsoft.AspNetCore.DataProtection; +using StackExchange.Redis; class Program { @@ -15,4 +16,15 @@ public class Startup : DefaultStartup public Startup(IConfiguration configuration) : base(configuration) { } + + public override void ConfigureServices(IServiceCollection services) + { + base.ConfigureServices(services); + + //todo + var redis = ConnectionMultiplexer.Connect($"192.168.199.30:30115,defaultDatabase:1,password=zxc111"); + services.AddDataProtection() + .SetApplicationName("basic") + .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys"); + } } \ No newline at end of file diff --git a/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/DeviceTaskAssignmentsController.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/DeviceTaskAssignmentsController.cs index 6b72836c..1a8ba8ec 100644 --- a/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/DeviceTaskAssignmentsController.cs +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/DeviceTaskAssignmentsController.cs @@ -32,4 +32,14 @@ public class DeviceTaskAssignmentsController : ControllerBase { return await _deviceTaskAssignmentService.GetPageAsync(request); } + + /// + /// 获取设备任务(按设备) + /// + /// + [HttpGet("device-tasks")] + public async Task> DeviceGetTasksAsync([FromQuery] DeviceTaskGetRequest request) + { + return await _deviceTaskAssignmentService.DeviceGetTasksAsync(request); + } } diff --git a/Src/Dlhis.ScheduledTask/TaskAssignment/FaceUrlOptions.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/FaceUrlOptions.cs new file mode 100644 index 00000000..89d05a98 --- /dev/null +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/FaceUrlOptions.cs @@ -0,0 +1,14 @@ +using Kurisu.Core.ConfigurableOptions.Attributes; + +namespace Dlhis.ScheduledTask.TaskAssignment; + +[Configuration] +public class FaceUrlOptions +{ + public string Url { get; set; } + + /// + /// 过期时间:秒 + /// + public int Limit { get; set; } +} diff --git a/Src/Dlhis.ScheduledTask/TaskAssignment/Request/DeviceTaskGetRequest.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Request/DeviceTaskGetRequest.cs new file mode 100644 index 00000000..612c6eec --- /dev/null +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Request/DeviceTaskGetRequest.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations; +using Kurisu.AspNetCore.Utils.Extensions; +using Kurisu.Core.DataAccess.Dto; + +namespace Dlhis.ScheduledTask.TaskAssignment.Request; + +public class DeviceTaskGetRequest : PageDto, IValidatableObject +{ + /// + /// 品牌 + /// + public string Brand { get; set; } + + /// + /// 设备号 + /// + public string DeviceUniqueNo { get; set; } + + public IEnumerable Validate(ValidationContext validationContext) + { + if (Brand.IsEmpty() && DeviceUniqueNo.IsEmpty()) + { + yield return new ValidationResult("设备品牌和设备唯一号不能都为空", new[] { nameof(Brand), nameof(DeviceUniqueNo) }); + } + } +} diff --git a/Src/Dlhis.ScheduledTask/TaskAssignment/Response/DeviceConnectionResponse.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Response/DeviceConnectionResponse.cs new file mode 100644 index 00000000..492756a5 --- /dev/null +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Response/DeviceConnectionResponse.cs @@ -0,0 +1,19 @@ +namespace Dlhis.ScheduledTask.TaskAssignment.Response; + +public class DeviceConnectionResponse +{ + /// + /// 品牌 + /// + public string Brand { get; set; } + + /// + /// 设备唯一号 + /// + public string DeviceUniqueNo { get; set; } + + /// + /// 连接信息 + /// + public string ConnectionInfo { get; set; } +} diff --git a/Src/Dlhis.ScheduledTask/TaskAssignment/Response/DeviceTaskToDeviceResponse.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Response/DeviceTaskToDeviceResponse.cs new file mode 100644 index 00000000..ab6bd4ce --- /dev/null +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Response/DeviceTaskToDeviceResponse.cs @@ -0,0 +1,27 @@ +namespace Dlhis.ScheduledTask.TaskAssignment.Response; + +/// +/// 设备维度任务 +/// +public class DeviceTaskToDeviceByDeviceResponse +{ + /// + /// 品牌 + /// + public string Brand { get; set; } + + /// + /// 设备唯一号 + /// + public string DeviceUniqueNo { get; set; } + + /// + /// 连接信息 + /// + public string DeviceConnectionInfo { get; set; } + + /// + /// 任务 + /// + public List Tasks { get; set; } +} diff --git a/Src/Dlhis.ScheduledTask/TaskAssignment/Response/TaskCombineUserDimensionDto.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Response/TaskCombineUserDimensionDto.cs new file mode 100644 index 00000000..a9725d53 --- /dev/null +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Response/TaskCombineUserDimensionDto.cs @@ -0,0 +1,27 @@ +using Dlhis.Entity.Device.Enums; +using Kurisu.AspNetCore.Utils.Extensions; + +namespace Dlhis.ScheduledTask.TaskAssignment.Response; + +public class TaskCombineUserDimensionDto +{ + /// + /// 任务id + /// + public long TaskId { get; set; } + + /// + /// 任务类型 + /// + public DeviceTaskEnumType Type { get; set; } + + /// + /// 任务类型描述 + /// + public string TypeDesc => Type.GetDescription(); + + /// + /// 用户下发信息 + /// + public UserToDeviceResponse UserInfo { get; set; } +} diff --git a/Src/Dlhis.ScheduledTask/TaskAssignment/Response/UserToDeviceResponse.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Response/UserToDeviceResponse.cs new file mode 100644 index 00000000..4d8e3b79 --- /dev/null +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Response/UserToDeviceResponse.cs @@ -0,0 +1,42 @@ +using Newtonsoft.Json; + +namespace Dlhis.ScheduledTask.TaskAssignment.Response; + +public class UserToDeviceResponse +{ + /// + /// 人员档案号 + /// + public string UserNo { get; set; } + + /// + /// 人员学工号 + /// + public string UserCode { get; set; } + + /// + /// 人员名称 + /// + public string UserName { get; set; } + + /// + /// 部门号 + /// + public string DepartmentNo { get; set; } + + /// + /// 部门名称 + /// + public string DepartmentName { get; set; } + + + /// + /// 卡号 + /// + public string CardNo { get; set; } + + /// + /// 人脸 + /// + public string Face { get; set; } +} diff --git a/Src/Dlhis.ScheduledTask/TaskAssignment/Services/IDeviceTaskAssignmentService.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Services/IDeviceTaskAssignmentService.cs index 578d3570..c38a81a4 100644 --- a/Src/Dlhis.ScheduledTask/TaskAssignment/Services/IDeviceTaskAssignmentService.cs +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Services/IDeviceTaskAssignmentService.cs @@ -7,4 +7,11 @@ namespace Dlhis.ScheduledTask.TaskAssignment.Services; public interface IDeviceTaskAssignmentService : IScopeDependency { Task> GetPageAsync(DeviceTaskAssignmentRequest request); + + /// + /// 设备获取任务 + /// + /// + /// + Task> DeviceGetTasksAsync(DeviceTaskGetRequest request); } diff --git a/Src/Dlhis.ScheduledTask/TaskAssignment/Services/Implements/DeviceTaskAssignmentService.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Services/Implements/DeviceTaskAssignmentService.cs index 7aed6893..0952e3c8 100644 --- a/Src/Dlhis.ScheduledTask/TaskAssignment/Services/Implements/DeviceTaskAssignmentService.cs +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Services/Implements/DeviceTaskAssignmentService.cs @@ -1,32 +1,44 @@ -using Dlhis.Entity.Device.Entities; +using System.Linq.Expressions; +using Dlhis.Entity.Basic.Entity; +using Dlhis.Entity.Device.Entities; +using Dlhis.Entity.Device.Enums; using Dlhis.ScheduledTask.TaskAssignment.Request; using Dlhis.ScheduledTask.TaskAssignment.Response; +using Kurisu.AspNetCore.Scope; +using Kurisu.AspNetCore.UnifyResultAndValidation; +using Kurisu.AspNetCore.Utils.Extensions; using Kurisu.Core.DataAccess.Dto; using Kurisu.SqlSugar.Extensions; using Kurisu.SqlSugar.Services; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.Options; +using SqlSugar; namespace Dlhis.ScheduledTask.TaskAssignment.Services.Implements; public class DeviceTaskAssignmentService : IDeviceTaskAssignmentService { private readonly IDbContext _dbContext; + private readonly ILogger _logger; - public DeviceTaskAssignmentService(IDbContext dbContext) + public DeviceTaskAssignmentService(IDbContext dbContext, ILogger logger) { _dbContext = dbContext; + _logger = logger; } public async Task> GetPageAsync(DeviceTaskAssignmentRequest request) { var page = await _dbContext.Queryable() - .Select((deviceTask) => new DeviceTaskAssignmentResponse + .LeftJoin((deviceTask, ga) => deviceTask.UserNo == ga.No) + .Select((deviceTask, ga) => new DeviceTaskAssignmentResponse { DeviceUniqueNo = deviceTask.DeviceUniqueNo, ResultMessage = deviceTask.ResultMessage, RetryCount = deviceTask.RetryCount, Status = deviceTask.Status, UserNo = deviceTask.UserNo, - UserName = deviceTask.UserName, + UserName = ga.Name, UserCode = deviceTask.UserCode, Type = deviceTask.Type, LastUpdateTime = deviceTask.ModifiedTime @@ -35,4 +47,137 @@ public class DeviceTaskAssignmentService : IDeviceTaskAssignmentService return page; } + + public async Task> DeviceGetTasksAsync(DeviceTaskGetRequest request) + { + var data = await ContinueUpdateAsync(async () => + { + var page = await _dbContext.Queryable() + .LeftJoin((deviceTask, deivce) => deviceTask.DeviceUniqueNo == deivce.UniqueNo) + .LeftJoin((deviceTask, deivce, deivceTamplate) => deivceTamplate.Code == deivce.TemplateCode) + .LeftJoin((deviceTask, deivce, deivceTamplate, ga) => deviceTask.UserNo == ga.No) + .LeftJoin((deviceTask, deivce, deivceTamplate, ga, department) => department.No == ga.DepartmentNo) + .WhereIF(request.Brand.IsPresent(), (deviceTask, deivce, deivceTamplate) => deivceTamplate.Brand == request.Brand) + .WhereIF(request.DeviceUniqueNo.IsPresent(), (deviceTask, deivce) => deviceTask.DeviceUniqueNo == request.DeviceUniqueNo) + .Where(deviceTask => deviceTask.Status != DeviceTaskStatusEnumType.Success) + .OrderBy(deviceTask => deviceTask.CreateTime) + .Select((deviceTask, deivce, deivceTamplate, ga, department) => new + { + deviceTask.Id, + deviceTask.Type, + deviceTask.DeviceUniqueNo, + DeviceConnectionInfo = deivce.ConnectionInfo, + deivce.Brand, + deviceTask.UserNo, + deviceTask.UserCode, + UserName = ga.Name, + ga.DepartmentNo, + DepartmentName = department.Name, + ga.CardNo, + deviceTask.Version + }) + .ToPageListAsync(request); + + var taskIdVs = page.Data.Select(x => new { x.Id, x.Version }).ToList(); + Expression> where = LinqExpressionExtension.False(); + taskIdVs.ForEach(p => + { + where = where.Or(x => x.Id == p.Id && x.Version == p.Version && x.Status != DeviceTaskStatusEnumType.Success); + }); + + await _dbContext.Client.Ado.BeginTranAsync(); + try + { + var effecet = await _dbContext.Updateable() + .SetColumns(x => x.Version == x.Version + 1) + .SetColumns(x => x.Status == DeviceTaskStatusEnumType.Process) + .SetColumns(x => x.ModifiedTime == DateTime.Now) + .Where(where) + .ExecuteCommandAsync(); + + if (taskIdVs.Count != effecet) + { + throw new VersionExceptions("更新错误"); + } + + await _dbContext.Client.Ado.CommitTranAsync(); + } + catch + { + await _dbContext.Client.Ado.RollbackTranAsync(); + throw; + } + + return page.Data; + }, 5); + + return Scoped.Request.Value.Create((sp) => + { + var faceUrlOptions = sp.GetService>().Value; + var dataProtectionProvider = sp.GetService(); + + var timeLimitedDataProtector = dataProtectionProvider + .CreateProtector("down:face") + .ToTimeLimitedDataProtector(); + + return data.GroupBy(x => new { x.Brand, x.DeviceUniqueNo, x.DeviceConnectionInfo }) + .Select(x => + { + var b = x.Key.Brand; + var d = x.Key.DeviceUniqueNo; + var dc = x.Key.DeviceConnectionInfo; + + return new DeviceTaskToDeviceByDeviceResponse + { + Brand = b, + DeviceUniqueNo = d, + DeviceConnectionInfo = dc, + Tasks = x.AsEnumerable().Select(item => + { + var key = $"face:{item.UserCode}"; + var token = timeLimitedDataProtector.Protect(key, TimeSpan.FromSeconds(faceUrlOptions.Limit)); + + return new TaskCombineUserDimensionDto + { + TaskId = item.Id, + Type = item.Type, + UserInfo = new UserToDeviceResponse + { + UserNo = item.UserNo, + UserCode = item.UserCode, + UserName = item.UserName, + DepartmentNo = item.DepartmentNo, + DepartmentName = item.DepartmentName, + CardNo = item.CardNo, + Face = faceUrlOptions.Url + token + } + }; + }).ToList() + }; + + }).ToList(); + }); + } + + + private async Task ContinueUpdateAsync(Func> func, int retry) + { + for (int i = 0; i < retry; i++) + { + try + { + return await func(); + } + catch (Exception ex) when (ex is VersionExceptions) + { + _logger.LogWarning(ex, ex.Message); + } + catch (Exception) + { + throw; + } + } + + throw new UserFriendlyException("操作失败,请重试"); + } } diff --git a/Src/Dlhis.ScheduledTask/appsettings.Development.json b/Src/Dlhis.ScheduledTask/appsettings.Development.json index 17b935d5..fbfb5dd0 100644 --- a/Src/Dlhis.ScheduledTask/appsettings.Development.json +++ b/Src/Dlhis.ScheduledTask/appsettings.Development.json @@ -5,6 +5,10 @@ "Microsoft.AspNetCore": "Warning" } }, + "FaceUrlOptions": { + "Url": "http://localhost:5002/api/gainfos/face?token=", + "Limit": 7200 + }, "SwaggerOptions": { "Enable": true, "Authority": "https://yikatong.isawesome.cn/oauth2", diff --git a/Src/Dlhis.ScheduledTask/appsettings.json b/Src/Dlhis.ScheduledTask/appsettings.json index c6eceea5..ae228d61 100644 --- a/Src/Dlhis.ScheduledTask/appsettings.json +++ b/Src/Dlhis.ScheduledTask/appsettings.json @@ -8,6 +8,7 @@ "SqlSugarOptions": { "DefaultConnectionString": "server=192.168.199.124;port=3306;userid=root;password=dlhis123;database=yikatong;charset=utf8mb4;", "SlaveConnectionString": [], + "FaceConnectionString": "server=192.168.199.124;port=3306;userid=root;password=dlhis123;database=face;charset=utf8mb4;", "Timeout": 30, "SlowSqlTime": 1, "EnableSqlLog": true @@ -15,6 +16,10 @@ "ConnectionStrings": { "HangfireConnection": "server=192.168.199.124;port=3306;userid=root;password=dlhis123;database=HangFire;charset=utf8mb4;Allow User Variables=true;" }, + "FaceUrlOptions": { + "Url": "https://yikatong.isawesome.cn/api/basic/gainfos/face?token=", + "Limit": 7200 + }, "SwaggerOptions": { "Enable": true, "Authority": "http://identity.oauth.svc.cluster.local",