Commit 0802839d by 李承祥

数据抽取接口实现

parent 9d7daa95
......@@ -27,6 +27,7 @@ public class TemplateController : Controller
private IHostingEnvironment evn;
private ClaimService claim;
private Application application;
private WebapiUrl url;
private readonly AllotService allotService;
public TemplateController(TemplateService templateService,
HospitalService hospitalService,
......@@ -34,6 +35,7 @@ public class TemplateController : Controller
IHostingEnvironment evn,
ClaimService claim,
IOptions<Application> options,
IOptions<WebapiUrl> url,
AllotService allotService)
{
this.templateService = templateService;
......@@ -42,6 +44,7 @@ public class TemplateController : Controller
this.evn = evn;
this.claim = claim;
this.application = options.Value;
this.url = url.Value;
this.allotService = allotService;
}
......@@ -116,8 +119,15 @@ public ApiResponse ExtractData([CustomizeValidator(RuleSet = "Template"), FromBo
return new ApiResponse(ResponseType.Fail, "医院无效");
var user = claim.At(request.Token);
string param = JsonHelper.Serialize(new
{
id = request.ID,
mail = user.Mail,
hospitalId = hospital.ID
});
HttpHelper.HttpPost(url.ExtractData, param, true);
//extractService.ExtractData(request.ID, user.Mail, hospital);
BackgroundJob.Enqueue(() => extractService.ExtractData(request.ID, user.Mail, hospital));
//BackgroundJob.Enqueue(() => extractService.ExtractData(request.ID, user.Mail, hospital));
return new ApiResponse(ResponseType.OK, "HIS绩效数据提取任务正在执行,稍后我们将以邮件的通知您!");
}
......@@ -145,5 +155,38 @@ public IActionResult DownFile([FromQuery]AllotRequest request)
var memi = provider.Mappings[fileExt];
return File(memoryStream, memi, Path.GetFileName(allot.ExtractPath));
}
/// <summary>
/// 保存提取文件
/// </summary>
/// <param name="form"></param>
/// <returns></returns>
[Route("savefile")]
[HttpPost]
public ApiResponse SaveFile([FromForm] IFormCollection form, int allotId, int hospitalId)
{
var file = ((FormFileCollection)form.Files).FirstOrDefault();
if (file == null)
return new ApiResponse(ResponseType.Error, "上传文件无效");
var dpath = Path.Combine(evn.ContentRootPath, "Files", $"{hospitalId}", "autoextract");
FileHelper.CreateDirectory(dpath);
var path = Path.Combine(dpath, FileHelper.GetFileName(file.FileName));
using (var stream = file.OpenReadStream())
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
if (!FileHelper.CreateFile(path, bytes))
return new ApiResponse(ResponseType.Error, "保存失败");
}
var allot = allotService.GetAllot(allotId);
allot.ExtractPath = path;
if (!string.IsNullOrEmpty(path) && allotService.Update(allot))
return new ApiResponse(ResponseType.OK, "上传成功!");
else
return new ApiResponse(ResponseType.Error);
}
}
}
\ No newline at end of file
......@@ -55,10 +55,11 @@ public void ConfigureServices(IServiceCollection services)
.Configure<AppConnection>(Configuration.GetSection("AppConnection"))
.Configure<Application>(Configuration.GetSection("Application"))
.Configure<HuyiSmsConfig>(Configuration.GetSection("HuyiSmsConfig"))
.Configure<EmailOptions>(Configuration.GetSection("EmailOptions"));
.Configure<EmailOptions>(Configuration.GetSection("EmailOptions"))
.Configure<WebapiUrl>(Configuration.GetSection("WebapiUrl"));
#endregion
var connection = services.BuildServiceProvider().GetService<IOptions<AppConnection>>();
var connection = services.BuildServiceProvider().GetService<IOptions<AppConnection>>();
#region json & fluentvalidation & filter
services
......
......@@ -22,5 +22,9 @@
"DirectorRole": "4",
"AbsolutePath": "E:\\wwwroot\\testjx.suvalue.com",
"HttpPath": "http://testjx.suvalue.com:81"
},
"WebapiUrl": {
"ExtractData": "http://localhost:50997/api/extract/index",
"ImportFile": "http://localhost:5001/api/template/savefile"
}
}
......@@ -37,5 +37,9 @@
"Receiver": [ "chengxiang.li@suvalue.com", "486035085@qq.com" ],
"AbsolutePath": "E:\\wwwroot\\testjx.suvalue.com",
"HttpPath": "http://testjx.suvalue.com:81"
},
"WebapiUrl": {
"ExtractData": "http://localhost:50997/api/extract/index",
"ImportFile": "http://localhost:5001/api/template/savefile"
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Performance.DtoModels.AppSettings
{
public class WebapiUrl
{
/// <summary>
/// 抽取数据地址
/// </summary>
public string ExtractData { get; set; }
/// <summary>
/// 上传文件地址
/// </summary>
public string ImportFile { get; set; }
}
}
......@@ -23,6 +23,11 @@ public class AllotRequest : ApiRequest
/// 绩效发放月
/// </summary>
public int Month { get; set; }
/// <summary>
/// 邮箱
/// </summary>
public string Mail { get; set; }
}
public class AllotRequestValidator : AbstractValidator<AllotRequest>
......
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Performance.DtoModels;
using Performance.DtoModels.AppSettings;
using Performance.Infrastructure;
using Performance.Services;
namespace Performance.Extract.Api.Controllers
{
[Route("api/[controller]")]
public class ExtractController : Controller
{
private readonly ExtractService extractService;
private readonly HospitalService hospitalService;
private readonly WebapiUrl url;
private readonly ILogger<ExtractController> logger;
public ExtractController(ExtractService extractService, HospitalService hospitalService,
IOptions<WebapiUrl> url, ILogger<ExtractController> logger)
{
this.extractService = extractService;
this.hospitalService = hospitalService;
this.url = url.Value;
this.logger = logger;
}
[HttpPost]
[Route("index")]
public void Index([FromBody]AllotRequest request)
{
var hospital = hospitalService.GetHopital(request.HospitalId.Value);
var filepath = extractService.ExtractData(request.ID, request.Mail, hospital);
if (!string.IsNullOrEmpty(filepath) && FileHelper.IsExistFile(filepath))
{
int i = 1;
while (i <= 5)
{
string retJson = HttpHelper.HttpClient(url.ImportFile + $"?allotId={request.ID}&hospitalId={hospital.ID}", filepath);
logger.LogInformation(retJson);
var ret = JsonHelper.Deserialize<ApiResponse>(retJson);
if ((int)ret.State == 1)
break;
i++;
}
}
}
}
}
\ No newline at end of file
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Performance.DtoModels;
using Performance.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Performance.Extract.Api
{
public class ExceptionsFilter : IAsyncExceptionFilter
{
private readonly ILogger<ExceptionsFilter> _logger;
public ExceptionsFilter(ILogger<ExceptionsFilter> logger)
{
this._logger = logger;
}
public Task OnExceptionAsync(ExceptionContext context)
{
if (context.Exception is PerformanceException)
{
_logger.LogWarning($"接口错误警告:{context.Exception.ToString()}");
var response = new ApiResponse(ResponseType.Fail, context.Exception.Message);
context.Result = new ObjectResult(response);
LogHelper.Warning(JsonHelper.Serialize(response), "接口错误警告");
}
else if (context.Exception is PerformanceTokenErrorException)
{
_logger.LogWarning($"Token Error:{context.Exception.ToString()}");
var response = new ApiResponse(ResponseType.TokenError, context.Exception.Message);
context.Result = new ObjectResult(response);
LogHelper.Warning(JsonHelper.Serialize(response), "Token Error");
}
else
{
_logger.LogError($"接口异常:{context.Exception.ToString()}");
var response = new ApiResponse(ResponseType.Error, "接口内部异常", context.Exception.Message);
context.Result = new ObjectResult(response);
LogHelper.Error(JsonHelper.Serialize(response), "接口内部异常");
}
return Task.CompletedTask;
}
}
}
......@@ -6,8 +6,17 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.0" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.5.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Performance.Services\Performance.Services.csproj" />
</ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties appsettings_1json__JSONSchema="" /></VisualStudio></ProjectExtensions>
</Project>
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using FluentValidation;
using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NLog.Extensions.Logging;
using Performance.DtoModels.AppSettings;
using Performance.DtoModels.AutoMapper;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Services;
namespace Performance.Extract.Api
{
......@@ -24,17 +37,98 @@ public Startup(IConfiguration configuration)
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
LogHelper.Initialize(Configuration.GetSection("AppConnection:RedisConnectionString").Value, "MTEzMTAyMzEzNDYzMzY5MzE4NA");
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
#region appsetting注入
services
.Configure<AppConnection>(Configuration.GetSection("AppConnection"))
.Configure<Application>(Configuration.GetSection("Application"))
.Configure<EmailOptions>(Configuration.GetSection("EmailOptions"))
.Configure<WebapiUrl>(Configuration.GetSection("WebapiUrl"));
#endregion
var connection = services.BuildServiceProvider().GetService<IOptions<AppConnection>>();
#region json & fluentvalidation & filter
services
//筛选器配置
.AddMvc(option =>
{
option.Filters.Add<ExceptionsFilter>();
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
//json格式配置
.AddJsonOptions(json =>
{
json.SerializerSettings.Converters.Add(new IsoDateTimeConverterContent() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
json.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
json.SerializerSettings.ContractResolver = new LowercaseContractResolver();
json.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Include;
json.SerializerSettings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
json.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
json.SerializerSettings.Culture = new CultureInfo("it-IT");
json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
})
//model验证
.AddFluentValidation(fv =>
{
//禁用其他以使FluentValidation是唯一执行的验证库
fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
var assembly = Assembly.Load("Performance.DtoModels");
var types = ReflectionHelper.GetInstances<IValidator>(assembly);
foreach (var type in types)
{
fv.RegisterValidatorsFromAssemblyContaining(type.GetType());
}
});
#endregion
#region service注入 repoitory注入
services
.AddPerformanceService()
.AddPerformanceRepoitory();
#endregion
#region automapper
Mapper.Initialize(cfg => cfg.AddProfile<AutoMapperConfigs>());
services.AddAutoMapper();
#endregion
#region email
//阿里邮箱配置
var emailOption = services.BuildServiceProvider().GetService<IOptions<EmailOptions>>();
//邮件发送
services.AddEmailUtil(options =>
{
options.Account = emailOption.Value.Account;
options.Password = emailOption.Value.Password;
options.SmtpServer = emailOption.Value.SmtpServer;
});
#endregion
#region //ef配置
services.AddDbContext<PerformanceDbContext>(options =>
{
options.UseMySQL(connection.Value.PerformanceConnectionString);
});
#endregion
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddNLog();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
loggerFactory.CreateLogger<Startup>().LogDebug(env.EnvironmentName);
app.UseMvc();
}
}
......
......@@ -4,5 +4,39 @@
"Default": "Warning"
}
},
"AllowedHosts": "*"
"AllowedHosts": "*",
//连接字符串
"AppConnection": {
"PerformanceConnectionString": "server=192.168.18.166;database=db_performance;uid=root;pwd=1234qwer;pooling=true;charset=utf8;convert zero datetime=true;port=3306;connection timeout=120;max pool size=512;allow user variables=true;",
"HangfireConnectionString": "server=192.168.18.166;database=db_hangfire;uid=root;pwd=1234qwer;port=3306;allow user variables=true;",
"RedisConnectionString": "116.62.245.55:6379,defaultDatabase=2"
},
//互亿
"HuyiSmsConfig": {
"Url": "http://106.ihuyi.cn/webservice/sms.php?method=Submit",
"Account": "cf_szjk",
"Password": "123456"
},
//阿里邮箱
"EmailOptions": {
"SmtpServer": "smtpdm.aliyun.com",
"Account": "service@email.suvalue.com",
"Password": "SuValue123456"
},
"Application": {
//登录过期时间
"ExpirationMinutes": "120",
//验证码过期
"SmsCodeMinutes": "30",
//短信模板
"SmsTemplate": "溯直健康提醒您,您的验证码为:[code],当天有效!",
//邮件指定接收人
"Receiver": [ "chengxiang.li@suvalue.com", "486035085@qq.com" ],
"AbsolutePath": "E:\\wwwroot\\testjx.suvalue.com",
"HttpPath": "http://testjx.suvalue.com:81"
},
"WebapiUrl": {
"ExtractData": "http://localhost:50997/api/extract/index",
"ImportFile": "http://localhost:5001/api/template/savefile"
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
......@@ -105,6 +107,29 @@ public static bool CheckValidationResult(object sender, X509Certificate certific
{ // 总是接受
return true;
}
/// <summary>
/// 请求文件 post file
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="file">文件路径</param>
/// <returns></returns>
public static string HttpClient(string url, string file)
{
try
{
WebClient client = new WebClient();
client.Credentials = CredentialCache.DefaultCredentials;
client.Headers.Add("Content-Type", "application/form-data");//注意头部必须是form-data
client.QueryString["path"] = file;
byte[] fileb = client.UploadFile(new Uri(url), "POST", file);
string res = Encoding.UTF8.GetString(fileb);
return res;
}
catch (Exception ex)
{
throw ex;
}
}
}
}
\ No newline at end of file
......@@ -70,7 +70,7 @@ public class ExtractService : IAutoInjection
this.perforHospitalconfigRepository = perforHospitalconfigRepository;
}
public void ExtractData(int allotId, string mail, sys_hospital hospital)
public string ExtractData(int allotId, string mail, sys_hospital hospital)
{
LogHelper.Information($"开始执行绩效数据提取任务{new { allotId, mail, hospital }}", "提取绩效数据");
List<PerSheet> sheetList = new List<PerSheet>();
......@@ -129,25 +129,29 @@ public void ExtractData(int allotId, string mail, sys_hospital hospital)
if (WriteExcel(path, originalPath, sheetList, hospitalConfig, hospital.ID, allotList.First(t => t.ID == allotId), out string filepath))
{
LogHelper.Information($"基础数据提取完成,文件保存成功{filepath}", "提取绩效数据");
var allot = allotList.First(t => t.ID == allotId);
allot.ExtractPath = filepath;
if (!string.IsNullOrEmpty(filepath))
perforPerallotRepository.Update(allot);
//var allot = allotList.First(t => t.ID == allotId);
//allot.ExtractPath = filepath;
//if (!string.IsNullOrEmpty(filepath))
// perforPerallotRepository.Update(allot);
SendEmail(mail, filepath, $"{hospital.HosName}HIS数据提取成功", $"{hospital.HosName}{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}成功提取。");
return filepath;
}
return "";
}
catch (PerformanceException ex)
{
logger.LogError(ex.ToString());
LogHelper.Error(ex.ToString(), "提取绩效数据", "异常");
SendEmail(mail, "", $"{hospital.HosName}HIS数据提取失败", $"{hospital.HosName}提取数据失败,{ex.Message}!");
throw ex;
}
catch (Exception ex)
{
logger.LogError(ex.ToString());
LogHelper.Error(ex.ToString(), "提取绩效数据", "异常");
SendEmail(mail, "", $"{hospital.HosName}HIS数据提取失败", $"{hospital.HosName}提取数据过程中出现异常情况,我们将尽快解决问题。给您带来的不便我们深感歉意!");
throw ex;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment