Merge branch 'refs/heads/development'
This commit is contained in:
37
Src/Dlhis.Middle/Api/FaceBearerTokenHandler.cs
Normal file
37
Src/Dlhis.Middle/Api/FaceBearerTokenHandler.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Text;
|
||||
using Dlhis.Middle.Response;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
using Kurisu.RemoteCall.Abstractions;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dlhis.Middle.Api
|
||||
{
|
||||
public class FaceBearerTokenHandler : IAuthTokenHandler
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string GetToken(IServiceProvider serviceProvider)
|
||||
{
|
||||
var cache = serviceProvider.GetService<IMemoryCache>();
|
||||
if (cache.TryGetValue("token", out string token)) return "Bearer " + token;
|
||||
|
||||
var httpClient = serviceProvider.GetService<IHttpClientFactory>().CreateClient("face");
|
||||
var hostName = serviceProvider.GetService<IConfiguration>().GetSection("HostName").Value;
|
||||
|
||||
var tokenResponse = httpClient.PostAsync($"https://{hostName}/api/user/oauth2/clientgrant", new StringContent(JsonConvert.SerializeObject(new
|
||||
{
|
||||
ClientId = "e509c2aaa98e300c",
|
||||
ClientSecret = "6184d8979fc48105"
|
||||
}), Encoding.UTF8, "application/json")).GetAwaiter().GetResult();
|
||||
|
||||
var tokenJson = tokenResponse.Content.ReadAsStringAsync().GetAwaiter().GetResult();
|
||||
var tokenInfo = JsonConvert.DeserializeObject<DefaultApiResult<TokenResponse>>(tokenJson);
|
||||
|
||||
token = tokenInfo.Data.AccessToken;
|
||||
|
||||
cache.Set("token", token, TimeSpan.FromSeconds(tokenInfo.Data.Expires));
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Src/Dlhis.Middle/Api/IAssignmentDeviceTaskApi.cs
Normal file
14
Src/Dlhis.Middle/Api/IAssignmentDeviceTaskApi.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Dlhis.Middle.Request;
|
||||
using Dlhis.Middle.Response;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
using Kurisu.RemoteCall.Attributes;
|
||||
|
||||
namespace Dlhis.Middle.Api;
|
||||
|
||||
[EnableRemoteClient(Name = "face-service", BaseUrl = "${Authority}")]
|
||||
public interface IAssignmentDeviceTaskApi
|
||||
{
|
||||
[Auth(TokenHandler = typeof(FaceBearerTokenHandler))]
|
||||
[Post("/api/scheduled/assignments/deviceTasks")]
|
||||
Task<DefaultApiResult<List<DeviceTaskToDeviceByDeviceResponse>>> DeviceGetTasksAsync(DeviceTaskGetRequest request);
|
||||
}
|
||||
15
Src/Dlhis.Middle/Api/ICanteenApi.cs
Normal file
15
Src/Dlhis.Middle/Api/ICanteenApi.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Dlhis.Middle.Request;
|
||||
using Dlhis.Middle.Response;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
using Kurisu.RemoteCall.Attributes;
|
||||
|
||||
namespace Dlhis.Middle.Api;
|
||||
|
||||
[EnableRemoteClient(Name = "face-service", BaseUrl = "${Authority}")]
|
||||
public interface ICanteenApi
|
||||
{
|
||||
|
||||
[Auth(TokenHandler = typeof(FaceBearerTokenHandler))]
|
||||
[Post("/api/canteen/orders")]
|
||||
Task<DefaultApiResult<OrderResultResponse>> AddAsync(OrderAddRequest request);
|
||||
}
|
||||
76
Src/Dlhis.Middle/Controllers/AssignmentsController.cs
Normal file
76
Src/Dlhis.Middle/Controllers/AssignmentsController.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using Dlhis.Entity.Device.Enums;
|
||||
using Dlhis.Middle.Api;
|
||||
using Dlhis.Middle.Request;
|
||||
using Dlhis.Middle.Response;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Aop;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Dlhis.Middle.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// 任务分配
|
||||
/// </summary>
|
||||
[Route("api/scheduled/[controller]")]
|
||||
[ApiController]
|
||||
public class AssignmentsController : ControllerBase
|
||||
{
|
||||
private readonly IAssignmentDeviceTaskApi _assignmentDeviceTaskApi;
|
||||
private readonly string _internalIp;
|
||||
|
||||
public AssignmentsController(IAssignmentDeviceTaskApi assignmentDeviceTaskApi, IConfiguration configuration)
|
||||
{
|
||||
_assignmentDeviceTaskApi = assignmentDeviceTaskApi;
|
||||
_internalIp = configuration.GetSection("InternalIP").Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取设备任务(按设备)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[IgnoreTenant]
|
||||
[HttpGet("deviceTasks")]
|
||||
public async Task<DefaultApiResult<List<DeviceTaskToDeviceByDeviceResponse>>> DeviceGetTasksGetAsync([FromQuery] DeviceTaskGetRequest request)
|
||||
{
|
||||
var result = await _assignmentDeviceTaskApi.DeviceGetTasksAsync(request);
|
||||
foreach (var data in result.Data)
|
||||
{
|
||||
foreach (var task in data.Tasks.Where(x => x.Type != DeviceTaskEnumType.Delete))
|
||||
{
|
||||
var currentUser = JObject.FromObject(task.Info).ToObject<UserToDeviceResponse>();
|
||||
var token = QueryHelpers.ParseQuery(currentUser.Face).First().Value;
|
||||
currentUser.Face = $"http://{_internalIp}/api/basic/gainfos/face?token=" + token;
|
||||
|
||||
task.Info = currentUser;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取设备任务(按设备)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("deviceTasks")]
|
||||
[IgnoreTenant]
|
||||
public async Task<DefaultApiResult<List<DeviceTaskToDeviceByDeviceResponse>>> DeviceGetTasksPostAsync(DeviceTaskGetRequest request)
|
||||
{
|
||||
var result = await _assignmentDeviceTaskApi.DeviceGetTasksAsync(request);
|
||||
foreach (var data in result.Data)
|
||||
{
|
||||
foreach (var task in data.Tasks.Where(x => x.Type != DeviceTaskEnumType.Delete))
|
||||
{
|
||||
var currentUser = JObject.FromObject(task.Info).ToObject<UserToDeviceResponse>();
|
||||
var token = QueryHelpers.ParseQuery(currentUser.Face).First().Value;
|
||||
currentUser.Face = $"http://{_internalIp}/api/basic/gainfos/face?token=" + token;
|
||||
|
||||
task.Info = currentUser;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
52
Src/Dlhis.Middle/Controllers/GainfosController.cs
Normal file
52
Src/Dlhis.Middle/Controllers/GainfosController.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Dlhis.Middle.Filters;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Dlhis.Middle.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// sap档案表
|
||||
/// </summary>
|
||||
[Route("api/basic/[controller]")]
|
||||
[ApiController]
|
||||
public class GainfosController : ControllerBase
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public GainfosController(IHttpClientFactory httpClientFactory, IConfiguration configuration)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过token获取人脸照片,失效或者找不到返回HttpStatus404状态码
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[NotFound]
|
||||
[AllowAnonymous]
|
||||
[HttpGet("face")]
|
||||
public async Task<IActionResult> GetFaceAsync(string token)
|
||||
{
|
||||
var hostName = _configuration.GetSection("HostName").Value;
|
||||
var httpClient = _httpClientFactory.CreateClient();
|
||||
|
||||
try
|
||||
{
|
||||
var faceBytes = await httpClient.GetByteArrayAsync($"https://{hostName}/api/basic/gainfos/face?token={token}");
|
||||
|
||||
if (faceBytes.Length == 0)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
|
||||
return new FileContentResult(faceBytes, "image/png");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
using Dlhis.Middle.Request;
|
||||
using Dlhis.Middle.Api;
|
||||
using Dlhis.Middle.Request;
|
||||
using Dlhis.Middle.Response;
|
||||
using Dlhis.Middle.Services;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Aop;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Dlhis.Middle.Controllers;
|
||||
@@ -15,11 +14,11 @@ namespace Dlhis.Middle.Controllers;
|
||||
[ApiController]
|
||||
public class OrdersController : ControllerBase
|
||||
{
|
||||
private readonly IOrderService _orderService;
|
||||
private readonly ICanteenApi _canteenApi;
|
||||
|
||||
public OrdersController(IOrderService orderService)
|
||||
public OrdersController(ICanteenApi canteenApi)
|
||||
{
|
||||
_orderService = orderService;
|
||||
_canteenApi = canteenApi;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -31,6 +30,6 @@ public class OrdersController : ControllerBase
|
||||
[IgnoreTenant]
|
||||
public async Task<DefaultApiResult<OrderResultResponse>> AddAsync(OrderAddRequest request)
|
||||
{
|
||||
return await _orderService.AddAsync(request);
|
||||
return await _canteenApi.AddAsync(request);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Kurisu.RemoteCall" Version="0.4.2" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="8.0.6" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" />
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlcipher" Version="2.1.8" />
|
||||
|
||||
27
Src/Dlhis.Middle/Dto/TaskCombineDto.cs
Normal file
27
Src/Dlhis.Middle/Dto/TaskCombineDto.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using Dlhis.Entity.Device.Enums;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
|
||||
namespace Dlhis.Middle.Dto;
|
||||
|
||||
public class TaskCombineDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务id
|
||||
/// </summary>
|
||||
public long TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务类型
|
||||
/// </summary>
|
||||
public DeviceTaskEnumType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务类型描述
|
||||
/// </summary>
|
||||
public string TypeDesc => Type.GetDescription();
|
||||
|
||||
/// <summary>
|
||||
/// 下发信息
|
||||
/// </summary>
|
||||
public object Info { get; set; }
|
||||
}
|
||||
30
Src/Dlhis.Middle/Filters/NotFoundAttribute.cs
Normal file
30
Src/Dlhis.Middle/Filters/NotFoundAttribute.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace Dlhis.Middle.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<object>;
|
||||
|
||||
if (apiResult.Data is ProblemDetails _)
|
||||
{
|
||||
context.Result = new NotFoundResult();
|
||||
//context.HttpContext.Response
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await next();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using Dlhis.Middle.Services;
|
||||
using Dlhis.Middle.Services.Implements;
|
||||
using Kurisu.AspNetCore;
|
||||
using Kurisu.AspNetCore.Startup;
|
||||
using Microsoft.IdentityModel.Logging;
|
||||
|
||||
@@ -23,6 +24,8 @@ public class Startup : DefaultStartup
|
||||
public override void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
base.ConfigureServices(services);
|
||||
|
||||
services.AddRemoteCall(App.ActiveTypes);
|
||||
services.AddHttpClient("face").ConfigurePrimaryHttpMessageHandler(() =>
|
||||
{
|
||||
var handler = new HttpClientHandler
|
||||
|
||||
42
Src/Dlhis.Middle/Request/DeviceTaskGetRequest.cs
Normal file
42
Src/Dlhis.Middle/Request/DeviceTaskGetRequest.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Dlhis.Entity.Device.Enums;
|
||||
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
|
||||
namespace Dlhis.Middle.Request;
|
||||
|
||||
public class DeviceTaskGetRequest : PageDto, IValidatableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// 品牌
|
||||
/// </summary>
|
||||
public string Brand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备号
|
||||
/// </summary>
|
||||
public string DeviceUniqueNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务类型
|
||||
/// </summary>
|
||||
public List<DeviceTaskEnumType> Types { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取处理中的任务
|
||||
/// </summary>
|
||||
public bool IsProcess { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 厂区
|
||||
/// </summary>
|
||||
public string Factory { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (Brand.IsEmpty() && DeviceUniqueNo.IsEmpty() && Factory.IsEmpty())
|
||||
{
|
||||
yield return new ValidationResult("设备品牌,设备号和厂区不能都为空", new[] { nameof(Brand), nameof(DeviceUniqueNo), nameof(Factory) });
|
||||
}
|
||||
}
|
||||
}
|
||||
29
Src/Dlhis.Middle/Response/DeviceTaskToDeviceResponse.cs
Normal file
29
Src/Dlhis.Middle/Response/DeviceTaskToDeviceResponse.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Dlhis.Middle.Dto;
|
||||
|
||||
namespace Dlhis.Middle.Response;
|
||||
|
||||
/// <summary>
|
||||
/// 设备任务
|
||||
/// </summary>
|
||||
public class DeviceTaskToDeviceByDeviceResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// 品牌
|
||||
/// </summary>
|
||||
public string Brand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备唯一号
|
||||
/// </summary>
|
||||
public string DeviceUniqueNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备信息
|
||||
/// </summary>
|
||||
public object DeviceInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务
|
||||
/// </summary>
|
||||
public List<TaskCombineDto> Tasks { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Kurisu.AspNetCore.CustomClass;
|
||||
|
||||
namespace Dlhis.Middle.Response;
|
||||
|
||||
public class UploadRecordToDeviceResponse
|
||||
{
|
||||
public DateTimePeriod DateTimePeriod { get; set; }
|
||||
}
|
||||
71
Src/Dlhis.Middle/Response/UserToDeviceResponse.cs
Normal file
71
Src/Dlhis.Middle/Response/UserToDeviceResponse.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using Kurisu.AspNetCore.CustomClass;
|
||||
|
||||
namespace Dlhis.Middle.Response;
|
||||
|
||||
public class UserToDeviceResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// 人员唯一id
|
||||
/// </summary>
|
||||
public long UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人员档案号
|
||||
/// </summary>
|
||||
public string UserNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 老系统档案号
|
||||
/// </summary>
|
||||
public string OldUserNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人员学工号
|
||||
/// </summary>
|
||||
public string UserCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人员名称
|
||||
/// </summary>
|
||||
public string UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 部门号
|
||||
/// </summary>
|
||||
public string DepartmentNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 部门名称
|
||||
/// </summary>
|
||||
public string DepartmentName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 卡号
|
||||
/// </summary>
|
||||
public string CardNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人脸
|
||||
/// </summary>
|
||||
public string Face { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 有效日期范围
|
||||
/// </summary>
|
||||
public DatePeriod ValidDatePeriod { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 控制门[1,2,3....]
|
||||
/// </summary>
|
||||
public List<int> Doors { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 时段[1,2,3....]
|
||||
/// </summary>
|
||||
public List<int> TimePeriods { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 假期计划id
|
||||
/// </summary>
|
||||
public int Schedule { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user