diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs index c9d921f8..d14bb97f 100644 --- a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs +++ b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs @@ -182,6 +182,7 @@ public class OrderService : IOrderService await _dbContext.Updateable() .SetColumns(x => x.OrderStatus == CanteenOrderStatusEnumType.Failure) .SetColumns(x => x.Result == ex.Message) + .SetColumns(x => x.ModifiedTime == DateTime.Now) .Where(x => x.Id == orderId) .ExecuteCommandAsync(); @@ -190,6 +191,7 @@ public class OrderService : IOrderService await _dbContext.Updateable() .SetColumns(x => x.OrderStatus == CanteenOrderStatusEnumType.Successful) + .SetColumns(x => x.ModifiedTime == DateTime.Now) .Where(x => x.Id == orderId) .ExecuteCommandAsync(); } diff --git a/Src/Dlhis.Entity/Device/Entities/DeviceTask.cs b/Src/Dlhis.Entity/Device/Entities/DeviceTask.cs index 2185c284..4d0b5a4b 100644 --- a/Src/Dlhis.Entity/Device/Entities/DeviceTask.cs +++ b/Src/Dlhis.Entity/Device/Entities/DeviceTask.cs @@ -33,11 +33,6 @@ public class DeviceTaskEntity : SugarBaseEntity, ITenantId, IVersion /// public string DeviceUniqueNo { get; set; } - /// - /// 重试次数 - /// - public int RetryCount { get; set; } - /// /// 任务下发状态 /// diff --git a/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/AssignmentsController.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/AssignmentsController.cs new file mode 100644 index 00000000..6250a029 --- /dev/null +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/AssignmentsController.cs @@ -0,0 +1,54 @@ +using Dlhis.ScheduledTask.TaskAssignment.Request; +using Dlhis.ScheduledTask.TaskAssignment.Response; +using Dlhis.ScheduledTask.TaskAssignment.Services; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Dlhis.ScheduledTask.TaskAssignment.Controllers; + +/// +/// 任务分配 +/// +[Authorize] +[Route("api/[controller]")] +[ApiController] +public class AssignmentsController : ControllerBase +{ + private readonly IAssignmentService _assignmentService; + + public AssignmentsController(IAssignmentService assignmentService) + { + _assignmentService = assignmentService; + } + + /// + /// 获取设备任务(按设备) + /// + /// + [HttpGet("devicetasks")] + public async Task> DeviceGetTasksGetAsync([FromQuery] DeviceTaskGetRequest request) + { + return await _assignmentService.DeviceGetTasksAsync(request); + } + + /// + /// 获取设备任务(按设备) + /// + /// + [HttpPost("devicetasks")] + public async Task> DeviceGetTasksPostAsync(DeviceTaskGetRequest request) + { + return await _assignmentService.DeviceGetTasksAsync(request); + } + + /// + /// 更新任务状态 + /// + /// + /// + [HttpPost("taskstatus")] + public async Task UpdateDeviceTaskStatusAsync(UpdateDeviceTaskStatusRequest request) + { + await _assignmentService.UpdateDeviceTaskStatusAsync(request); + } +} diff --git a/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/DeviceTaskAssignmentsController.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/DeviceTaskAssignmentsController.cs index 1a8ba8ec..6b72836c 100644 --- a/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/DeviceTaskAssignmentsController.cs +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Controllers/DeviceTaskAssignmentsController.cs @@ -32,14 +32,4 @@ 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/Request/UpdateDeviceTaskStatusRequest.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Request/UpdateDeviceTaskStatusRequest.cs new file mode 100644 index 00000000..5db0375f --- /dev/null +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Request/UpdateDeviceTaskStatusRequest.cs @@ -0,0 +1,19 @@ +namespace Dlhis.ScheduledTask.TaskAssignment.Request; + +public class UpdateDeviceTaskStatusRequest +{ + /// + /// 任务id + /// + public long TaskId { get; set; } + + /// + /// 是否执行成功 + /// + public bool IsSuccess { get; set; } + + /// + /// 处理结果描述 + /// + public string ResultMessage { get; set; } +} diff --git a/Src/Dlhis.ScheduledTask/TaskAssignment/Services/IAssignmentService.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Services/IAssignmentService.cs new file mode 100644 index 00000000..5fa65f35 --- /dev/null +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Services/IAssignmentService.cs @@ -0,0 +1,22 @@ +using Dlhis.ScheduledTask.TaskAssignment.Request; +using Dlhis.ScheduledTask.TaskAssignment.Response; + +namespace Dlhis.ScheduledTask.TaskAssignment.Services; + +public interface IAssignmentService : IScopeDependency +{ + /// + /// 设备获取任务 + /// + /// + /// + Task> DeviceGetTasksAsync(DeviceTaskGetRequest request); + + + /// + /// 更新设备任务状态 + /// + /// + /// + Task UpdateDeviceTaskStatusAsync(UpdateDeviceTaskStatusRequest request); +} diff --git a/Src/Dlhis.ScheduledTask/TaskAssignment/Services/IDeviceTaskAssignmentService.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Services/IDeviceTaskAssignmentService.cs index c38a81a4..578d3570 100644 --- a/Src/Dlhis.ScheduledTask/TaskAssignment/Services/IDeviceTaskAssignmentService.cs +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Services/IDeviceTaskAssignmentService.cs @@ -7,11 +7,4 @@ 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/AssignmentService.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Services/Implements/AssignmentService.cs new file mode 100644 index 00000000..d9b53edf --- /dev/null +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Services/Implements/AssignmentService.cs @@ -0,0 +1,206 @@ +using Dlhis.Entity.Basic.Entity; +using Dlhis.Entity.Device.Entities; +using Dlhis.Entity.Device.Enums; +using System.Linq.Expressions; +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.SqlSugar.Services; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.Options; +using SqlSugar; +using Kurisu.SqlSugar.Extensions; +using Kurisu.SqlSugar.Attributes; + +namespace Dlhis.ScheduledTask.TaskAssignment.Services.Implements; + +[IgnoreTenant] +public class AssignmentService : IAssignmentService +{ + private readonly IDbContext _dbContext; + private readonly ILogger _logger; + + public AssignmentService(IDbContext dbContext, ILogger logger) + { + _dbContext = dbContext; + _logger = logger; + } + + 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.Wait) + .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); + + if (!page.Data.Any()) + { + return page.Data; + } + + 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); + + if (!data.Any()) + { + return new List(); + } + + 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(); + }); + } + + + public async Task UpdateDeviceTaskStatusAsync(UpdateDeviceTaskStatusRequest request) + { + for (int i = 0; i < 5; i++) + { + var deviceTask = await _dbContext.Queryable().Where(x => x.Id == request.TaskId).SingleAsync(); + deviceTask.ThrowIfNull("设备任务不存在"); + (deviceTask.Status != DeviceTaskStatusEnumType.Process) + .ThrowIfTrue($"任务状态[{deviceTask.Status.GetDescription()}]有误"); + + var status = request.IsSuccess ? DeviceTaskStatusEnumType.Success : DeviceTaskStatusEnumType.Error; + + var effect = await _dbContext.Updateable() + .SetColumns(x => x.Status == status) + .SetColumns(x => x.ResultMessage == request.ResultMessage) + .SetColumns(x => x.Version == x.Version + 1) + .SetColumns(x => x.ModifiedTime == DateTime.Now) + .Where(x => x.Id == request.TaskId && x.Version == deviceTask.Version) + .ExecuteCommandAsync(); + + if (effect == 0) + { + continue; + } + + return; + } + + throw new UserFriendlyException("操作失败,请重试"); + } + + + //*********************************************************** help methods ********************************************************************* + + 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/TaskAssignment/Services/Implements/DeviceTaskAssignmentService.cs b/Src/Dlhis.ScheduledTask/TaskAssignment/Services/Implements/DeviceTaskAssignmentService.cs index 0952e3c8..4462a4cc 100644 --- a/Src/Dlhis.ScheduledTask/TaskAssignment/Services/Implements/DeviceTaskAssignmentService.cs +++ b/Src/Dlhis.ScheduledTask/TaskAssignment/Services/Implements/DeviceTaskAssignmentService.cs @@ -1,30 +1,20 @@ -using System.Linq.Expressions; -using Dlhis.Entity.Basic.Entity; +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, ILogger logger) + public DeviceTaskAssignmentService(IDbContext dbContext) { _dbContext = dbContext; - _logger = logger; } public async Task> GetPageAsync(DeviceTaskAssignmentRequest request) @@ -35,7 +25,7 @@ public class DeviceTaskAssignmentService : IDeviceTaskAssignmentService { DeviceUniqueNo = deviceTask.DeviceUniqueNo, ResultMessage = deviceTask.ResultMessage, - RetryCount = deviceTask.RetryCount, + RetryCount = deviceTask.Version, Status = deviceTask.Status, UserNo = deviceTask.UserNo, UserName = ga.Name, @@ -48,136 +38,4 @@ 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("操作失败,请重试"); - } }