Commit 84545835 by tangzhongyang

流水库展示拉取

parents
# All files: detect if file is text automatically
* text=auto
# Text files that should be normalized to LF
*.cs text diff=csharp
*.config text
*.sln text
*.csproj text
*.md text
*.sh text
*.ps1 text
*.cmd text
*.bat text
*.markdown text
*.msbuild text
# Binary files that should not be normalized or diffed
*.exe binary
*.dll binary
*.pdb binary
*.pfx binary
*.snk binary
*.png binary
*.gif binary
*.jpg binary
*.bmp binary
*.ico binary
*.chm binary
*.7z binary
*.zip binary
tools/SHFB/**/* binary
tools/Wix/**/* binary
tools/SHFB export-ignore
tools/Sandcastle export-ignore
tools/Wix export-ignore
obj/
bin/
Bin/
msbuild.log
LastTestRunSummary.cmd
src/Docs/Working/
test-results/
*.chw
*.pidb
*.userprefs
log.txt
*.suo
_ReSharper.*
*.ReSharper.user
*.bak
*.csproj.user
*.vcxproj.user
TestResults/
StyleCop.Cache
NLogMerged.api.xml
_UpgradeReport_Files/
UpgradeLog*.XML
*.xap
ipch/
*.sdf
*.opensdf
examples/NLogDemo/logs/
examples/NLogDemo/gmail*.txt
*.ncrunchsolution
*.user
tools/FAKE/
packages/
build/
*.sublime-*
*.DotSettings
*.vshost.*
.vs
.cr
/artifacts
健康体检
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "3.1.9",
"commands": [
"dotnet-ef"
]
}
}
}
\ No newline at end of file
using Health.Api.Infrastructure;
using Health.Api.Infrastructure.Queries;
using Health.Api.Infrastructure.Request;
using Health.Infra;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System;
using System.Net;
using System.Security.Claims;
namespace Health.Api.Controllers
{
[Authorize]
[Route("api/account")]
[ApiController]
public class AccountController : ControllerBase
{
private readonly IUserIdentity _identity;
private readonly UserQueries _userQueries;
private readonly JwtOption _jwtOption;
public AccountController(
IUserIdentity identity,
IOptions<JwtOption> options,
UserQueries userQueries)
{
_identity = identity;
_userQueries = userQueries;
_jwtOption = options.Value;
}
/// <summary>
/// 登录授权
/// </summary>
/// <remarks>
/// Sample request:
///
/// POST /Todo
/// {
/// "Account": "admin",
/// "Password": "1111"
/// }
///
/// </remarks>
/// <returns></returns>
[ProducesResponseType(typeof(JwtResult), (int)HttpStatusCode.OK)]
[HttpPost("login"), AllowAnonymous]
public ActionResult Login([FromBody] LoginRequest request)
{
var user = _userQueries.GetUserByAccount(request.Account, 0);
// 微信登录提示方式不同
if (user == null)
throw new DomainException("账号不存在");
if (!user.Password.Equals(request.Password, StringComparison.OrdinalIgnoreCase))
throw new DomainException("密码错误");
var claims = new[]
{
new Claim(ClaimTypes.Sid, user.ID.ToString()),
new Claim(ClaimTypes.Surname, user.RealName),
new Claim(ClaimTypes.Name, user.Login),
};
var jwt = new JwtToken(_jwtOption).GenerateToken(claims);
return Ok(jwt);
}
/// <summary>
/// 刷新登录JWT TOKEN
/// </summary>
/// <returns></returns>
[HttpPost]
[Route("refresh")]
public ActionResult Refresh()
{
var jwt = new JwtToken(_jwtOption).GenerateToken(_identity.Claims);
return Ok(jwt);
}
}
}
using Health.Api.Infrastructure.Enums;
using Health.Infra;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
namespace QueryPlatform.Api.Controllers
{
[Route("api/disease")]
[AllowAnonymous]
public class DiseaseController : ControllerBase
{
public DiseaseController()
{
}
//[HttpGet("{diseaseType}")]
//public ApiResponse<object> Get([FromRoute] string diseaseType, [FromQuery] string userId)
//{
// var diseaseTypes = EnumHelper.GetItems<DiseaseType>();
// if (diseaseTypes == null || !diseaseTypes.Select(t => t.Name).Contains(diseaseType))
// return new ApiResponse<object>(ResponseType.NotFound);
// diseaseType = diseaseTypes.FirstOrDefault(t => t.Name == diseaseType).Description;
// return new ApiResponse<object>();
//}
//[HttpPost]
//public ApiResponse Post()
//{
// return new ApiResponse();
//}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Health.Api.Infrastructure;
//using Health.Api.Infrastructure.Models;
using Health.Api.Infrastructure.Modules;
using Health.Api.Infrastructure.Queries;
using Health.Api.Infrastructure.Request;
using Health.Infra;
namespace Health.Api.Controllers
{
[Authorize]
[Route("api/resource")]
[ApiController]
public class ResourceController : ControllerBase
{
private readonly IMemoryCache _cache;
private readonly ResourceQueries resourceQueries;
public ResourceController(
IMemoryCache cache,
ResourceQueries resourceQueries)
{
this._cache = cache;
this.resourceQueries = resourceQueries;
}
/// <summary>
/// 查询当月项目
/// </summary>
/// <param name="source"> </param>
/// <returns></returns>
[HttpGet("ItemQuery")]
[AllowAnonymous]
public IEnumerable<dynamic> ItemQuery( )
{
var ItemQueryList = resourceQueries.ItemQuery( );
return ItemQueryList;
}
/// <summary>
/// 取消正在查询项目
/// </summary>
/// <param name="id">id </param>
/// <returns></returns>
[HttpPost("CancelProject")]
[AllowAnonymous]
public bool CancelProject(int id)
{
bool ItemQueryList = resourceQueries.CancelProject(id);
return ItemQueryList;
}
/// <summary>
/// 查询项目报告
/// </summary>
/// <param name="source">药品 疾病 同查 全部 </param>
/// <returns></returns>
[HttpPost("ProjectReport")]
[AllowAnonymous]
public (IEnumerable<dynamic> yearDistribution, IEnumerable<dynamic> regionalDistribution ,string queryCriteria,string title) ProjectReport([FromBody] SYS_Cs sYS_Cs)
{
return resourceQueries.ProjectReport(sYS_Cs.id, sYS_Cs.MEDIC_AREA, sYS_Cs.item_name, sYS_Cs.GENERIC_NAME, sYS_Cs.PROJECT_NAME, sYS_Cs.icd, sYS_Cs.DISEASE_NAME);
}
/// <summary>
/// 查询流水库表
/// </summary>
/// <returns></returns>
[HttpPost("QueryFlowDatabase")]
[AllowAnonymous]
public IEnumerable<dynamic> QueryFlowDatabase()
{
return resourceQueries.QueryFlowDatabase();
}
/// <summary>
/// 查询药品产地
/// </summary>
/// <returns></returns>
[HttpPost("ShowMEDIC_AREA")]
[AllowAnonymous]
public (IEnumerable<dynamic>, IEnumerable<dynamic>) ShowMEDIC_AREA(int id, int paseIndex)
{
return resourceQueries.ShowMEDIC_AREA(id, paseIndex);
}
/// <summary>
/// 查询名称产地
/// </summary>
/// <returns></returns>
[HttpPost("ShowITEM_NAME")]
[AllowAnonymous]
public (IEnumerable<dynamic>, IEnumerable<dynamic>) ShowITEM_NAME(int id, int paseIndex)
{
return resourceQueries.ShowITEM_NAME(id, paseIndex);
}
/// <summary>
/// 建立流水库表
/// </summary>
/// <returns></returns>
[HttpPost("EstablishFlowDatabaseTable")]
[AllowAnonymous]
public bool EstablishFlowDatabaseTable([FromBody] SYS_EstablishFlowDatabaseTable sYS_EstablishFlows)
{
return resourceQueries.EstablishFlowDatabaseTable(sYS_EstablishFlows.tableName, sYS_EstablishFlows.sql, sYS_EstablishFlows.id, sYS_EstablishFlows.remarks); ;
}
/// <summary>
/// 建立流水库
/// </summary>
/// <returns></returns>
[HttpPost("CreateAFlow_Library")]
[AllowAnonymous]
public bool CreateAFlow_Library(string DatabaseName,int indexs)
{
return resourceQueries.CreateAFlow_Library(DatabaseName,indexs);
}
/// <summary>
/// 查询日志
/// </summary>
/// <returns></returns>
[HttpPost("ShowLog")]
[AllowAnonymous]
public (IEnumerable<dynamic>, IEnumerable<dynamic>) ShowLog(int indexs, int paseIndex, string type)
{
return resourceQueries.ShowLog(indexs,paseIndex,type);
}
/// <summary>
/// 拉取流水库数据
/// </summary>
/// <returns></returns>
[HttpPost("PullData")]
[AllowAnonymous]
public void PullData(int indexs,string DatabaseName,string tableName)
{
resourceQueries.PullData(indexs, DatabaseName, tableName, "PUB_PATIENT");
//拉取登记
resourceQueries.PullData(indexs, DatabaseName, tableName, "OUT_REG_INFO");
resourceQueries.PullData(indexs, DatabaseName, tableName, "INPAT_REG_INFO");
//拉取诊断
resourceQueries.PullData(indexs, DatabaseName, tableName, "OUT_DIAG");
resourceQueries.PullData(indexs, DatabaseName, tableName, "INPAT_DIAG");
resourceQueries.PullData(indexs, DatabaseName, tableName, "OPS_INFO");
resourceQueries.PullData(indexs, DatabaseName, tableName, "ASSAY_REPORT");
resourceQueries.PullData(indexs, DatabaseName, tableName, "EXEC_REPORT");
resourceQueries.PullData1(indexs, DatabaseName, tableName, "OUT_PRES");
resourceQueries.PullData1(indexs, DatabaseName, tableName, "OUT_FEE");
resourceQueries.PullData1(indexs, DatabaseName, tableName, "INPAT_ORDER");
resourceQueries.PullData1(indexs, DatabaseName, tableName, "INPAT_FEE");
}
/// <summary>
/// 查询平台
/// </summary>
/// <returns></returns>
[HttpPost("Inquire")]
[AllowAnonymous]
public void Inquire(SYS_QueryConditions sYS_Query)
{
int type = 0;
if((!string.IsNullOrEmpty(sYS_Query.icd) || !string.IsNullOrEmpty(sYS_Query.diseaseName))&&string.IsNullOrEmpty(sYS_Query.drugName))
{
type = 1;
}
else if (string.IsNullOrEmpty(sYS_Query.icd) && string.IsNullOrEmpty(sYS_Query.diseaseName) && !string.IsNullOrEmpty(sYS_Query.drugName))
{
type = 2;
}
else if((!string.IsNullOrEmpty(sYS_Query.icd) || !string.IsNullOrEmpty(sYS_Query.diseaseName))&& !string.IsNullOrEmpty(sYS_Query.drugName))
{
}
else if (string.IsNullOrEmpty(sYS_Query.icd) &&string.IsNullOrEmpty(sYS_Query.diseaseName) &&string.IsNullOrEmpty(sYS_Query.drugName) && string.IsNullOrEmpty(sYS_Query.materialName))
{
}
else
{
throw new DomainException($@"材料费只支持单独查询!");
}
}
}
}
using Health.Api.Infrastructure.Modules;
using Health.Api.Infrastructure.Queries;
using Health.Api.Infrastructure.Request;
using Health.Infra;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Net;
namespace Health.Api.Controllers
{
[Route("api/user")]
[ApiController]
public class UserController : ControllerBase
{
private readonly IUserIdentity _identity;
private readonly UserStorage _userStorage;
private readonly UserQueries _userQueries;
public UserController(
IUserIdentity identity,
UserStorage userStorage,
UserQueries userQueries)
{
_identity = identity;
_userStorage = userStorage;
_userQueries = userQueries;
}
/// <summary>
/// 用户信息
/// </summary>
/// <returns></returns>
[ProducesResponseType(typeof(SYS_USER), (int)HttpStatusCode.OK)]
[HttpGet("info")]
public ActionResult Info()
{
var user = _userQueries.GetUserById(_identity.UserId);
if (user == null)
throw new DomainException("用户信息错误");
return Ok(user);
}
/// <summary>
/// 用户修改
/// </summary>
/// <returns></returns>
[ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.OK)]
[HttpPost("password")]
public IActionResult Update(UserRequest request)
{
//PasswordRequest
//if (string.IsNullOrEmpty(request.OldPassword)
// || string.IsNullOrEmpty(request.NewPassword)
// || request.NewPassword.Length < 4)
// throw new DomainException("参数错误");
//_userStorage.Update(_identity.UserId, request.OldPassword, request.NewPassword);
if (string.IsNullOrEmpty(request.ID.ToString()))
throw new DomainException("参数错误");
var user = _userQueries.GetUserByAccount(request.Login, request.ID);
if (user != null)
throw new DomainException("登录名称重复");
_userStorage.Update(request);
return Ok();
}
/// <summary>
/// 查询用户列表
/// </summary>
/// <returns></returns>
[ProducesResponseType(typeof(IEnumerable<SYS_USER>), (int)HttpStatusCode.OK)]
[HttpGet]
public IActionResult Get(string realname)
{
var users = _userQueries.GetUsers(realname);
return Ok(users);
}
/// <summary>
/// 新增用户
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[ProducesResponseType(typeof(SYS_USER), (int)HttpStatusCode.OK)]
[HttpPost]
public IActionResult Post(UserRequest request)
{
var user = _userQueries.GetUserByAccount(request.Login, 0);
if (user != null)
throw new DomainException("登录名称重复");
user = _userStorage.Add(request);
return Ok(user);
}
/// <summary>
/// 删除
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
[ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.OK)]
[HttpPost("delete/{userId}")]
public IActionResult Delete(int userId)
{
//delete: true
var user = _userStorage.Update(userId, delete: true);
return Ok(user);
}
/// <summary>
/// 禁用
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
[ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.OK)]
[HttpPost("disable/{userId}")]
public IActionResult Disable(int userId, bool zt)
{
//delete: true
var user = _userStorage.Update(userId, disable: zt);
return Ok(user);
}
/// <summary>
/// 重置密码
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
[ProducesResponseType(typeof(ApiResponse), (int)HttpStatusCode.OK)]
[HttpPost("reset/{userId}")]
public IActionResult Reset(int userId)
{
var user = _userStorage.Update(userId, reset: true);
return Ok(user.Password);
}
}
}
using Health.Infra;
using System.ComponentModel;
namespace Health.Api
{
public class ApiResponse<TEntity>
where TEntity : class, new()
{
public ResponseType StatusCode { get; set; }
/// <summary>
/// 消息内容。
/// </summary>
public string Message { get; set; }
/// <summary>
/// 返回数据。
/// </summary>
public TEntity Data { get; set; }
public ApiResponse()
: this(ResponseType.NotFound, EnumHelper.GetDescription(ResponseType.NotFound), null)
{
}
public ApiResponse(ResponseType type)
: this(type, EnumHelper.GetDescription(type), null)
{
}
public ApiResponse(ResponseType type, string message)
: this(type, message, null)
{
}
public ApiResponse(ResponseType type, TEntity entity)
: this(type, EnumHelper.GetDescription(type), entity)
{
}
public ApiResponse(ResponseType type, string message, TEntity entity)
{
StatusCode = type;
Message = message;
Data = entity;
}
}
public sealed class ApiResponse : ApiResponse<object>
{
public ApiResponse()
{
}
public ApiResponse(ResponseType type) : base(type)
{
}
public ApiResponse(ResponseType type, string message) : base(type, message)
{
}
public ApiResponse(ResponseType type, object entity) : base(type, entity)
{
}
public ApiResponse(ResponseType type, string message, object entity) : base(type, message, entity)
{
}
}
public enum ResponseType
{
/// <summary>
/// 执行成功
/// </summary>
[Description("执行成功")]
OK = 200,
/// <summary>
/// 参数错误
/// </summary>
[Description("参数错误")]
BadRequest = 400,
/// <summary>
/// 身份认证未授权
/// </summary>
[Description("身份认证未授权")]
Unauthorized = 401,
/// <summary>
/// 资源无效
/// </summary>
[Description("资源无效")]
NotFound = 404,
/// <summary>
/// 内部错误
/// </summary>
[Description("内部错误")]
InternalServerError = 500,
/// <summary>
/// 不支持请求
/// </summary>
[Description("不支持请求")]
NotImplemented = 501,
}
}
using Autofac;
using Health.Api.Infrastructure.Queries;
using Health.Api.Infrastructure.Queues;
using Microsoft.Extensions.Configuration;
namespace Health.Api.Infrastructure.AutofacModules
{
public class QueriesModule : Autofac.Module
{
private readonly IConfiguration configuration;
public QueriesModule(IConfiguration configuration)
{
this.configuration = configuration;
}
protected override void Load(ContainerBuilder builder)
{
var configConnectionString = configuration["ConnectionStrings:configConnectionString"];
var Connection151 = configuration["ConnectionStrings:Connection151"];
var Connection152 = configuration["ConnectionStrings:Connection152"];
var Connection153 = configuration["ConnectionStrings:Connection153"];
var Connection154 = configuration["ConnectionStrings:Connection154"];
var Connection155 = configuration["ConnectionStrings:Connection155"];
var Connection156 = configuration["ConnectionStrings:Connection156"];
var Connection158 = configuration["ConnectionStrings:Connection158"];
builder.RegisterType<HubNotificationQueue>().SingleInstance();
builder.Register(c => new UserStorage(configConnectionString)).InstancePerLifetimeScope();
builder.Register(c => new UserQueries(configConnectionString)).InstancePerLifetimeScope();
builder.Register(c => new ResourceQueries(Connection156, configConnectionString,Connection151,Connection152,Connection153,Connection154,Connection155,Connection158)).InstancePerLifetimeScope();
}
}
}
\ No newline at end of file
using Microsoft.EntityFrameworkCore;
namespace Health.Api
{
public class SearchContext : DbContext
{
public SearchContext(DbContextOptions<SearchContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
}
using CsvHelper;
using OfficeOpenXml;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
namespace Health.Api.Infrastructure.Domain
{
public class SearchPathInfo
{
private string relativePath; // 相对路径
public string resultPath; // 结果文件目录
public string filecode; // 标识
public SearchPathInfo(string rootPath, string directory)
{
filecode = Guid.NewGuid().ToString("N");
relativePath = $"/export/{directory}";
// 压缩路径
resultPath = Path.Combine(rootPath, "wwwroot", "export", directory);
TempPath = Path.Combine(rootPath, "wwwroot", "export", directory, filecode);
Directory.CreateDirectory(resultPath);
Directory.CreateDirectory(TempPath);
}
/// <summary>
/// 临时文件目录
/// </summary>
public string TempPath { get; private set; }
/// <summary>
/// 网络路径
/// </summary>
public string NetworkPath { get; private set; }
public void ClearTemp()
{
Directory.Delete(TempPath, true);
}
public void CreateFromDirectory(string fileName)
{
NetworkPath = $"{relativePath}/{fileName}_{filecode}.zip";
var filePath = Path.Combine(resultPath, $"{fileName}_{filecode}.zip");
ZipFile.CreateFromDirectory(TempPath, filePath);
}
}
public abstract class StorageFormat
{
public void Export(string tempPath, string name, IEnumerable<dynamic> dynamics)
{
Directory.CreateDirectory(tempPath);
ExportFile(tempPath, name, dynamics);
}
protected abstract void ExportFile(string tempPath, string name, IEnumerable<dynamic> dynamics);
}
public class StorageFormatCsv : StorageFormat
{
protected override void ExportFile(string tempPath, string name, IEnumerable<dynamic> dynamics)
{
string path = Path.Combine(tempPath, $"{name}.csv");
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate))
using (var writer = new StreamWriter(fs))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
csv.WriteRecords(dynamics);
csv.Flush();
}
}
}
public class StorageFormatExcel : StorageFormat
{
protected override void ExportFile(string tempPath, string name, IEnumerable<dynamic> dynamics)
{
string path = Path.Combine(tempPath, $"{name}.xlsx");
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate))
using (ExcelPackage package = new ExcelPackage(fs))
{
if (dynamics == null || dynamics.Count() == 0)
return;
var worksheet = package.Workbook.Worksheets.Add(name);
var headers = ((IDictionary<string, object>)dynamics.ElementAt(0)).Keys;
for (int col = 0; col < headers.Count; col++)
{
worksheet.SetValue(1, col + 1, headers.ElementAt(col));
}
for (int col = 0; col < headers.Count; col++)
{
for (int row = 0; row < dynamics.Count(); row++)
{
var key = headers.ElementAt(col);
var data = dynamics.ElementAt(row);
var temp = (IDictionary<string, object>)data;
var value = temp[key]?.ToString();
worksheet.SetValue(row + 2, col + 1, value);
}
}
package.Save();
}
}
}
}
using System.ComponentModel;
namespace Health.Api.Infrastructure.Enums
{
public enum DiseaseType
{
/// <summary>
/// 高血压
/// </summary>
[Description("高血压")]
g1,
/// <summary>
/// 糖尿病
/// </summary>
[Description("糖尿病")]
g2,
/// <summary>
/// 高血脂
/// </summary>
[Description("高血脂")]
g3,
}
}
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace Health.Api.Infrastructure.Filters
{
public class ArgumentsActionFilter : IActionFilter
{
private readonly ILogger<ArgumentsActionFilter> _logger;
public ArgumentsActionFilter(ILogger<ArgumentsActionFilter> logger)
{
_logger = logger;
}
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Exception == null)
{
object @object = null;
if (context.Result is ObjectResult)
@object = (context.Result as ObjectResult).Value;
context.Result = new ObjectResult(new OkResponse(@object));
}
}
public void OnActionExecuting(ActionExecutingContext context)
{
_logger.LogInformation($"请求地址:{context.HttpContext.Request.Path};请求内容 {JsonConvert.SerializeObject(context.ActionArguments)}");
}
}
}
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Linq;
using System.Net;
namespace Health.Api.Infrastructure.Filters
{
public class HttpGlobalExceptionFilter : IExceptionFilter
{
private readonly IWebHostEnvironment env;
private readonly ILogger<HttpGlobalExceptionFilter> logger;
public HttpGlobalExceptionFilter(IWebHostEnvironment env, ILogger<HttpGlobalExceptionFilter> logger)
{
this.env = env;
this.logger = logger;
}
public void OnException(ExceptionContext context)
{
logger.LogError(new EventId(context.Exception.HResult), context.Exception, context.Exception.Message);
if (context.Exception.GetType() == typeof(TokenErrorException))
{
context.Result = new ObjectResult(new UnauthorizedResponse());
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
}
else if (context.Exception.GetType() == typeof(DomainException))
{
if (context.Exception.InnerException?.GetType() == typeof(FluentValidation.ValidationException))
{
var validationException = context.Exception.InnerException as FluentValidation.ValidationException;
var result = new ParameterErrorResponse
{
Message = validationException.Message,
Instance = context.HttpContext.Request.Path,
};
var errors = validationException.Errors?.Select(err => err.ErrorMessage);
foreach (var item in validationException.Errors)
{
if (!result.Errors.ContainsKey(item.PropertyName))
result.Errors.Add(item.PropertyName, item.ErrorMessage);
}
context.Result = new BadRequestObjectResult(result);
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
else
{
var result = new DomainErrorResponse
{
Status = Status.Failed,
Message = context.Exception.Message,
Instance = context.HttpContext.Request.Path,
};
context.Result = new BadRequestObjectResult(result);
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
}
else
{
var result = new InternalServerErrorResponse
{
Status = Status.Failed,
Message = "请求发生一个未知错误,请参考错误信息。",
Instance = context.HttpContext.Request.Path,
};
if (env.IsDevelopment())
{
result.Developer = context.Exception;
}
context.Result = new BadRequestObjectResult(result);
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
}
context.ExceptionHandled = true;
}
}
}
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Linq;
using System.Net;
namespace Health.Api.Infrastructure.Filters
{
public class ValidateModelFilter : IResultFilter
{
private readonly ILogger<ValidateModelFilter> _logger;
public ValidateModelFilter(ILogger<ValidateModelFilter> logger)
{
_logger = logger;
}
public void OnResultExecuting(ResultExecutingContext context)
{
var response = context.Result as BadRequestObjectResult;
if (response != null && response.Value is ValidationProblemDetails)
{
var details = response.Value as ValidationProblemDetails;
var result = new ParameterErrorResponse
{
Message = "参数无效",
Instance = context.HttpContext.Request.Path,
};
foreach (var item in details.Errors)
{
if (!result.Errors.ContainsKey(item.Key) && item.Value.Any())
result.Errors.Add(item.Key, item.Value.First());
}
context.Result = new BadRequestObjectResult(result);
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
}
public void OnResultExecuted(ResultExecutedContext context)
{
if (context.Exception == null)
{
if (context.Result is ObjectResult)
{
var objectResult = (ObjectResult)context.Result;
var jsonData = JsonConvert.SerializeObject(objectResult.Value);
_logger.LogInformation($"请求地址:{context.HttpContext.Request.Path};响应结果:{jsonData}");
}
else if (context.Result is EmptyResult)
{
_logger.LogInformation($"请求地址:{context.HttpContext.Request.Path};没有响应结果");
}
}
}
}
}
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using System.IO;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace Health.Api
{
public class HealthCheck
{
public static Task WriteResponse(HttpContext context, HealthReport result)
{
context.Response.ContentType = "application/json; charset=utf-8";
var options = new JsonWriterOptions
{
Indented = true
};
using (var stream = new MemoryStream())
{
using (var writer = new Utf8JsonWriter(stream, options))
{
writer.WriteStartObject();
writer.WriteString("status", result.Status.ToString());
writer.WriteString("ip", context.Connection.RemoteIpAddress.ToString());
writer.WriteStartObject("results");
foreach (var entry in result.Entries)
{
writer.WriteStartObject(entry.Key);
writer.WriteString("status", entry.Value.Status.ToString());
writer.WriteString("description", entry.Value.Description);
writer.WriteStartObject("data");
foreach (var item in entry.Value.Data)
{
writer.WritePropertyName(item.Key);
JsonSerializer.Serialize(writer, item.Value, item.Value?.GetType() ?? typeof(object));
}
writer.WriteEndObject();
writer.WriteEndObject();
}
writer.WriteEndObject();
writer.WriteEndObject();
}
var json = Encoding.UTF8.GetString(stream.ToArray());
return context.Response.WriteAsync(json);
}
}
}
}
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Health.Api.Infrastructure.Hubs
{
[Authorize]
public class NotificationHub : Hub
{
public override Task OnConnectedAsync()
{
var userId = Context.User.Claims.FirstOrDefault(w => w.Type == ClaimTypes.Sid)?.Value;
Groups.AddToGroupAsync(Context.ConnectionId, userId);
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
var userId = Context.User.Claims.FirstOrDefault(w => w.Type == ClaimTypes.Sid)?.Value;
Groups.RemoveFromGroupAsync(Context.ConnectionId, userId);
return base.OnDisconnectedAsync(exception);
}
}
}
using Health.Infra;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace Health.Api.Infrastructure
{
public class JsonHelper : IJsonConverter
{
private readonly JsonSerializerSettings _serializerSettings;
public JsonHelper(IOptions<MvcNewtonsoftJsonOptions> options)
{
_serializerSettings = options.Value.SerializerSettings;
}
public T Deserialize<T>(string json)
{
return JsonConvert.DeserializeObject<T>(json, _serializerSettings);
}
public string Serialize(object @object)
{
return JsonConvert.SerializeObject(@object, Formatting.None, _serializerSettings);
}
}
}
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using System.Linq;
using System.Threading.Tasks;
namespace Health.Api.Infrastructure.Middlewares
{
/// <summary>
/// 解码中间件
/// </summary>
public class DecodeResponseMiddleware
{
private readonly RequestDelegate _next;
private readonly IConfiguration _configuration;
public DecodeResponseMiddleware(
RequestDelegate next,
IConfiguration configuration)
{
_next = next;
_configuration = configuration;
}
public async Task Invoke(HttpContext httpContext)
{
var metheds = new string[] { "PUT", "POST", "DELETE" };
if (metheds.Any(w => w.Equals(httpContext.Request.Method)))
{
//string privateKey = _configuration["PrivateKey"];
//var request = httpContext.Request;
//string secret = request.Headers["secret"];
//if (!string.IsNullOrEmpty(secret))
//{
// request.EnableBuffering();
// //把请求body流转换成字符串
// string body = await new StreamReader(request.Body).ReadToEndAsync();
// var data = AES.Decrypt(body, secret);
// var bytes = Encoding.UTF8.GetBytes(data);
// request.Body = new FileBufferingReadStream(new MemoryStream(bytes), 30720);
// request.Body.Seek(0, SeekOrigin.Begin);
// request.ContentType = "application/json";
//}
}
await _next(httpContext);
}
}
public static class DecodeResponseMiddlewareExtensions
{
public static IApplicationBuilder UseDecodeReqResponse(this IApplicationBuilder builder)
{
return builder.UseMiddleware<DecodeResponseMiddleware>();
}
}
}
using EasyCaching.Core;
using Health.Infra;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Health.Api.Infrastructure.Middlewares
{
/// <summary>
/// 解码中间件
/// </summary>
public class DoubleRequestMiddleware
{
private readonly RequestDelegate _next;
private readonly IEasyCachingProvider _provider;
public DoubleRequestMiddleware(
RequestDelegate next,
IEasyCachingProvider provider)
{
_next = next;
_provider = provider;
}
public async Task Invoke(HttpContext context)
{
var request = context.Request;
var timestamp = request.Headers["Timestamp"];
string body = await new StreamReader(request.Body).ReadToEndAsync();
StringBuilder @string = new StringBuilder();
@string
.Append(request.Method)
.Append(request.Scheme)
.Append(context.Connection.RemoteIpAddress)
.Append(context.Connection.RemotePort)
.Append(request.Path)
.Append(request.QueryString)
.Append(timestamp)
.Append(body);
var sign = Md5Util.Encrypt(@string.ToString());
var key = $"api.submit.sign.{sign}";
if (_provider.Exists(key))
{
var response = new DoubleSubmitResponse();
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(JsonConvert.SerializeObject(response));
return;
}
_provider.Set(key, DateTime.Now, TimeSpan.FromSeconds(20));
await _next(context);
}
}
public static class DoubleRequestMiddlewareExtensions
{
public static IApplicationBuilder UseDoubleRequest(this IApplicationBuilder builder)
{
return builder.UseMiddleware<DoubleRequestMiddleware>();
}
}
}
namespace Health.Api.Infrastructure.Modules
{
public class SYS_Cs
{
public int id { get; set; }
public string MEDIC_AREA { get; set; }
public string item_name { get; set; }
public string GENERIC_NAME { get; set; }
public string PROJECT_NAME { get; set; }
public string DISEASE_NAME { get; set; }
public string icd { get; set; }
}
public class SYS_EstablishFlowDatabaseTable
{
public int id { get; set; }
public string tableName { get; set; }
public string sql { get; set; }
public string remarks { get; set; }
}
}
namespace Health.Api.Infrastructure.Modules
{
public class SYS_Hospital
{
public int ID { get; set; }
public string HosName { get; set; }
public string ExecOpenLink { get; set; }
public string ExecDatabase { get; set; }
public string DataLoginName { get; set; }
public string DataPassword { get; set; }
}
public class SYS_QueryConditions
{
public int type { get; set; }
public string icd { get; set; }
public string diseaseName { get; set; }
public string drugName { get; set; }
public string materialName { get; set; }
}
}
using Newtonsoft.Json;
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Health.Api.Infrastructure.Modules
{
[Table("SYS_USER")]
public class SYS_USER
{
[Key]
public long ID { get; set; }
public DateTime CreateDate { get; set; }
public string RealName { get; set; }
public string Login { get; set; }
[JsonIgnore]
public string Password { get; set; }
///// <summary>
///// true 超级管理员 false 普通用户
///// </summary>
public bool States { get; set; }
/// <summary>
/// true 删除 false 正常
/// </summary>
public bool IsDelete { get; set; }
public bool IsDisable { get; set; }
}
}
using System;
namespace Health.Api.Infrastructure
{
public class Notification
{
public Notification(int userId, string method, PushContent body)
{
UserId = userId;
Method = method;
Body = body;
}
public int UserId { get; set; }
public string Method { get; set; }
public PushContent Body { get; set; }
public abstract class PushContent
{
protected PushContent(string content)
{
Content = content;
}
public abstract string Type { get; }
public string Time { get => DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); }
public string Content { get; set; }
}
}
public class EventContent : Notification.PushContent
{
public EventContent(object eventId, string subject, string content) : base(content)
{
EventId = eventId;
Subject = subject;
}
public object EventId { get; set; }
public string Subject { get; set; }
public override string Type => "Event";
}
public class TextContent : Notification.PushContent
{
public TextContent(string content) : base(content)
{
}
public override string Type => "Text";
}
}
using System.Collections.Generic;
namespace Health.Api.Infrastructure
{
public class Page
{
public Page() : this(1, 30) { }
public Page(int index) : this(index, 30) { }
public Page(int index, int size)
{
Index = index;
Size = size;
}
/// <summary>
/// 页码
/// </summary>
public int Index { get; set; }
/// <summary>
/// 页行数 默认30
/// </summary>
public int Size { get; set; }
}
public class Page<TEntity> : Page
{
public Page(int total, IEnumerable<TEntity> data)
{
Total = total;
Data = data;
}
public Page(int index, int size, int total, IEnumerable<TEntity> data)
: base(index, size)
{
Total = total;
Data = data;
}
public int Total { get; set; }
public IEnumerable<TEntity> Data { get; set; }
}
}
using Dapper;
using Dapper.Contrib.Extensions;
using Health.Api.Infrastructure.Modules;
using Microsoft.Data.SqlClient;
using StackExchange.Profiling;
using StackExchange.Profiling.Data;
using System.Collections.Generic;
using System.Data.Common;
namespace Health.Api.Infrastructure.Queries
{
public class UserQueries
{
private readonly string _connectionString;
public UserQueries(string connectionString)
{
_connectionString = connectionString;
}
public SYS_USER GetUserByAccount(string account, int id)
{
using (DbConnection connection = new ProfiledDbConnection(new SqlConnection(_connectionString), MiniProfiler.Current))
{
return connection.QueryFirstOrDefault<SYS_USER>("SELECT * FROM SYS_USER WHERE LOGIN=@account AND IsDelete=0 and id <>" + id, new { account });
}
}
public IEnumerable<SYS_USER> GetUsers(string realname)
{
using (DbConnection connection = new ProfiledDbConnection(new SqlConnection(_connectionString), MiniProfiler.Current))
{
return connection.Query<SYS_USER>("SELECT * FROM SYS_USER WHERE isdelete=0 and realname like '%" + realname + "%'");
}
}
public SYS_USER GetUserById(int userId)
{
using (DbConnection connection = new ProfiledDbConnection(new SqlConnection(_connectionString), MiniProfiler.Current))
{
return connection.Get<SYS_USER>(userId);
}
}
}
}
using Dapper.Contrib.Extensions;
using Health.Api.Infrastructure.Modules;
using Health.Api.Infrastructure.Request;
using Microsoft.Data.SqlClient;
using StackExchange.Profiling;
using StackExchange.Profiling.Data;
using System;
using System.Data.Common;
namespace Health.Api.Infrastructure.Queries
{
public class UserStorage
{
private readonly string _connectionString;
public UserStorage(string connectionString)
{
this._connectionString = connectionString;
}
public SYS_USER Add(UserRequest request)
{
using (DbConnection connection = new ProfiledDbConnection(new SqlConnection(_connectionString), MiniProfiler.Current))
{
var user = new SYS_USER
{
CreateDate = DateTime.Now,
Login = request.Login,
Password = request.Password,
RealName = request.RealName,
States = request.States,
IsDelete = false,
};
user.ID = connection.Insert(user);
return user;
}
}
/// <summary>
/// 修改密码
/// </summary>
/// <param name="userId"></param>
/// <param name="oldPassword"></param>
/// <param name="newPassword"></param>
/// <returns></returns>
public SYS_USER Update(UserRequest request)
{
using (DbConnection connection = new ProfiledDbConnection(new SqlConnection(_connectionString), MiniProfiler.Current))
{
var user = connection.Get<SYS_USER>(request.ID);
if (user == null)
throw new DomainException("账号不存在");
if (request.Password != "" && request.Password != null)
{
user.Password = request.Password;
}
user.Login = request.Login;
user.RealName = request.RealName;
user.States = request.States;
if (!connection.Update(user))
throw new DomainException("更新用户信息失败");
return user;
}
}
/// <summary>
/// 修改用户信息
/// </summary>
/// <param name="userId"></param>
/// <param name="delete"></param>
/// <param name="reset"></param>
/// <returns></returns>
public SYS_USER Update(int userId, bool? delete = null, bool? reset = null, bool? disable = null)
{
using (DbConnection connection = new ProfiledDbConnection(new SqlConnection(_connectionString), MiniProfiler.Current))
{
var user = connection.Get<SYS_USER>(userId);
if (user == null)
throw new DomainException("账号不存在");
if (delete.HasValue)
user.IsDelete = delete.Value;
if (reset.HasValue)
user.Password = "123456";
if (disable.HasValue)
user.IsDisable = disable.Value;
if (!connection.Update(user))
throw new DomainException("更新用户信息失败");
return user;
}
}
}
}
using Health.Api.Infrastructure.Hubs;
using Health.Infra;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
using System.Threading.Tasks;
namespace Health.Api.Infrastructure.Queues
{
public class HubNotificationQueue
{
private readonly IJsonConverter _converter;
private readonly ILogger<HubNotificationQueue> _logger;
private IHubContext<NotificationHub> _hubContext;
private BlockingCollection<Notification> _queue;
public HubNotificationQueue(
IJsonConverter converter,
ILogger<HubNotificationQueue> logger,
IHubContext<NotificationHub> hubContext)
{
_converter = converter;
_logger = logger;
_hubContext = hubContext;
_queue = new BlockingCollection<Notification>();
Task.Factory.StartNew(() => Consumer());
}
public void Send(Notification message)
{
_queue.TryAdd(message);
}
private void Consumer()
{
foreach (var item in _queue.GetConsumingEnumerable())
{
_logger.LogInformation("ConectionId GroupName:{ConectionId};消息推送:{Method};内容:{Body}", item.UserId.ToString(), item.Method, _converter.Serialize(item.Body));
_hubContext.Clients.Group(item.UserId.ToString()).SendAsync(item.Method, item.Body);
}
}
}
}
namespace Health.Api.Infrastructure.Request
{
public class LoginRequest
{
/// <summary>
/// 账号
/// </summary>
public string Account { get; set; }
/// <summary>
/// 密码
/// </summary>
public string Password { get; set; }
}
}
namespace Health.Api.Infrastructure.Request
{
public class PasswordRequest
{
public string OldPassword { get; set; }
public string NewPassword { get; set; }
}
}
namespace Health.Api.Infrastructure.Request
{
public class UserRequest
{
public int ID { get; set; }
public string RealName { get; set; }
public string Login { get; set; }
public string Password { get; set; }
public bool States { get; set; }
}
}
using Health.Infra;
using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
namespace Health.Api.Infrastructure
{
public class JwtOption
{
public string Secret { get; set; }
public string Issuer { get; set; }
public string Audience { get; set; }
public int Expires { get; set; }
}
public class JwtToken
{
private readonly byte[] secret;
private readonly string audience;
private readonly string issuer;
private readonly int expiresMinute;
public JwtToken(JwtOption options)
{
secret = Encoding.UTF8.GetBytes(options.Secret);
audience = options.Audience;
issuer = options.Issuer;
expiresMinute = options.Expires;
}
public JwtResult GenerateToken(IEnumerable<Claim> claims)
{
var authTime = DateTime.UtcNow;
var expiresAt = authTime.AddMinutes(expiresMinute);
var creds = new SigningCredentials(new SymmetricSecurityKey(secret), SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(issuer, audience, claims, DateTime.Now, DateTime.Now.AddHours(2), creds);
var tokenString = new JwtSecurityTokenHandler().WriteToken(token);
return new JwtResult
{
AccessToken = tokenString,
TokenType = "Bearer",
AuthTime = new DateTimeOffset(authTime).ToUnixTimeSeconds(),
ExpiresAt = new DateTimeOffset(expiresAt).ToUnixTimeSeconds(),
};
}
}
public class JwtResult
{
/// <summary>
/// Access Token
/// </summary>
public string AccessToken { get; set; }
/// <summary>
/// token 类型
/// </summary>
public string TokenType { get; set; }
/// <summary>
/// 授权时间
/// </summary>
public long AuthTime { get; set; }
/// <summary>
/// 过期时间
/// </summary>
public long ExpiresAt { get; set; }
}
public class UserIdentity : IUserIdentity
{
private readonly HttpContext _context;
public UserIdentity(IHttpContextAccessor contextAccessor)
{
_context = contextAccessor.HttpContext;
}
public int UserId
{
get
{
var claims = _context.User.Claims.ToArray();
var value = claims.FirstOrDefault(w => w.Type == ClaimTypes.Sid)?.Value;
if (!int.TryParse(value, out int userId))
throw new TokenErrorException();
return userId;
}
}
public IEnumerable<Claim> Claims
{
get
{
if (_context.User == null)
throw new TokenErrorException();
return _context.User.Claims;
}
}
public bool IsAuthenticated => _context.User.Identity.IsAuthenticated;
public bool TryClaim(string type, out string value)
{
if (_context.User == null)
throw new TokenErrorException();
value = _context.User.Claims?.FirstOrDefault(t => t.Type == type)?.Value;
return !string.IsNullOrEmpty(value);
}
}
}
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Serilog;
using System;
using System.IO;
namespace Health.Api
{
public class Program
{
static Program()
{
string env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
BaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
Configuration = new ConfigurationBuilder()
.SetBasePath(BaseDirectory)
.AddJsonFile($"appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env}.json", optional: true, reloadOnChange: true)
.AddJsonFile($"secret.json", optional: true, reloadOnChange: true)
.AddXmlFile($"overview.xml", true, true)
.AddEnvironmentVariables()
.Build();
}
public static IConfiguration Configuration { get; }
public static string BaseDirectory { get; }
public static void Main(string[] args)
{
Log.Logger = CreateSerilogLogger();
Log.Information("Starting web host");
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
var urls = Configuration.GetValue("ListenUrls", "http://*:56900");
return Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseUrls(urls.Split(','))
.UseStartup<Startup>();
})
.ConfigureAppConfiguration((context, config) =>
{
config.AddConfiguration(Configuration);
})
.UseContentRoot(BaseDirectory)
.UseSerilog();
}
private static Serilog.ILogger CreateSerilogLogger()
{
var basePath = Path.Combine(BaseDirectory, "logs");
return new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
//.MinimumLevel.Verbose()
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.File($"{basePath}\\.log", rollingInterval: RollingInterval.Day, retainedFileCountLimit: null)
.CreateLogger();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DeleteExistingFiles>True</DeleteExistingFiles>
<ExcludeApp_Data>False</ExcludeApp_Data>
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<PublishProvider>FileSystem</PublishProvider>
<PublishUrl>bin\Release\netcoreapp3.1\publish\</PublishUrl>
<WebPublishMethod>FileSystem</WebPublishMethod>
<SiteUrlToLaunchAfterPublish />
<TargetFramework>netcoreapp3.1</TargetFramework>
<ProjectGuid>e9d630a1-10fd-4dcf-abc2-d827dd79d8d4</ProjectGuid>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>
\ No newline at end of file
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:56900",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
//"ASPNETCORE_ENVIRONMENT": "Development"
"ASPNETCORE_ENVIRONMENT": "Localhost"
}
},
"Health.Api": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:56900",
"environmentVariables": {
//"ASPNETCORE_ENVIRONMENT": "Development"
"ASPNETCORE_ENVIRONMENT": "Localhost"
}
}
}
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UserSecretsId>07f301c6-3e68-4002-b677-5d2952bdb201</UserSecretsId>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>..\Health.Api\wwwroot\Health.Api.xml</DocumentationFile>
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Infrastructure\Models\INPAT_DIAG.cs" />
<Compile Remove="Infrastructure\Models\INPAT_FEE.cs" />
<Compile Remove="Infrastructure\Models\INPAT_ORDER.cs" />
<Compile Remove="Infrastructure\Models\INPAT_REG_INFO.cs" />
<Compile Remove="Infrastructure\Models\OUT_DIAG.cs" />
<Compile Remove="Infrastructure\Models\OUT_FEE.cs" />
<Compile Remove="Infrastructure\Models\OUT_PRES.cs" />
<Compile Remove="Infrastructure\Models\OUT_REG_INFO.cs" />
<Compile Remove="Infrastructure\Models\PUB_PATIENT.cs" />
</ItemGroup>
<ItemGroup>
<None Remove="index.html" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="index.html" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="15.0.8" />
<PackageReference Include="Dapper" Version="2.0.35" />
<PackageReference Include="Dapper.Contrib" Version="2.0.35" />
<PackageReference Include="EasyCaching.InMemory" Version="0.9.0" />
<PackageReference Include="EPPlus" Version="4.5.3.2" />
<PackageReference Include="MediatR" Version="8.1.0" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="8.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.8" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.7" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.8" />
<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.1" />
<PackageReference Include="Autofac" Version="5.2.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="FluentValidation" Version="9.2.0" />
<PackageReference Include="FluentValidation.AspNetCore" Version="9.2.0" />
<PackageReference Include="Serilog" Version="2.9.0" />
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="5.6.3" />
<PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Health.Infra\QueryPlatform.Infra.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Infrastructure\Dtos\" />
</ItemGroup>
<ItemGroup>
<Content Update="wwwroot\Health.Api.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Update="overview.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"JwtAuthorization": {
"Secret": "4pkCPn9PZcHXLCc276oX5GX5tRfdF1eg",
"Issuer": "suvalue.com",
"Audience": "suvalue.com",
"Expires": 120
},
"ConnectionStrings": {
"configConnectionString": "Server=192.168.18.181;Database=SV_QueryPlatform;User ID=sa;Password=Suvalue2016;Trusted_Connection=False;",
"Connection151": "Server=192.168.18.151;Database=DB_SV_Data_Config;User ID=sa;Password=Suvalue2016;Trusted_Connection=False;",
"Connection152": "Server=192.168.18.152;Database=DB_SV_Data_Config;User ID=sa;Password=Suvalue2016;Trusted_Connection=False;",
"Connection153": "Server=192.168.18.153;Database=DB_SV_Data_Config;User ID=sa;Password=Suvalue2016;Trusted_Connection=False;",
"Connection154": "Server=192.168.18.154;Database=DB_SV_Data_Config;User ID=sa;Password=Suvalue2016;Trusted_Connection=False;",
"Connection155": "Server=192.168.18.155;Database=DB_SV_Data_Config;User ID=sa;Password=Suvalue2016;Trusted_Connection=False;",
"Connection156": "Server=192.168.18.156;Database=DB_SV_Data_Config;User ID=sa;Password=srv@Ashersa;Trusted_Connection=False;",
"Connection158": "Server=192.168.18.158;Database=DB_SV_Data_Config;User ID=sa;Password=Suvalue2016;Trusted_Connection=False;"
}
}
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>%(DocumentTitle)</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css">
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
<script async="async" id="mini-profiler" src="/profiler/includes.min.js?v=4.2.1+b27bea37e9"
data-version="4.2.1+b27bea37e9" data-path="/profiler/"
data-current-id="18b79aef-14cc-44a4-b708-d4f72521a8cf" data-ids="" data-position="Left"
data-scheme="Light" data-authorized="true" data-max-traces="15" data-toggle-shortcut="Alt+P"
data-trivial-milliseconds="2.0" data-ignored-duplicate-execute-types="Open,OpenAsync,Close,CloseAsync"></script>
<style>
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
background: #fafafa;
}
</style>
%(HeadContent)
</head>
<body>
<div id="swagger-ui"></div>
<!-- Workaround for https://github.com/swagger-api/swagger-editor/issues/1371 -->
<script>
if (window.navigator.userAgent.indexOf("Edge") > -1) {
console.log("Removing native Edge fetch in favor of swagger-ui's polyfill")
window.fetch = undefined;
}
</script>
<script src="./swagger-ui-bundle.js"></script>
<script src="./swagger-ui-standalone-preset.js"></script>
<script>
window.onload = function () {
var configObject = JSON.parse('%(ConfigObject)');
var oauthConfigObject = JSON.parse('%(OAuthConfigObject)');
// Workaround for https://github.com/swagger-api/swagger-ui/issues/5945
configObject.urls.forEach(function (item) {
if (item.url.startsWith("http") || item.url.startsWith("/")) return;
item.url = window.location.href.replace("index.html", item.url).split('#')[0];
});
// If validatorUrl is not explicitly provided, disable the feature by setting to null
if (!configObject.hasOwnProperty("validatorUrl"))
configObject.validatorUrl = null
// If oauth2RedirectUrl isn't specified, use the built-in default
if (!configObject.hasOwnProperty("oauth2RedirectUrl"))
configObject.oauth2RedirectUrl = window.location.href.replace("index.html", "oauth2-redirect.html").split('#')[0];
// Apply mandatory parameters
configObject.dom_id = "#swagger-ui";
configObject.presets = [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset];
configObject.layout = "StandaloneLayout";
// Begin Swagger UI call region
const ui = SwaggerUIBundle(configObject);
ui.initOAuth(oauthConfigObject);
// End Swagger UI call region
window.ui = ui
}
</script>
</body>
</html>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8" ?>
<sql>
<!-- 人次汇总 -->
<GetPersonTimesCollect>
<![CDATA[
SELECT SOURCETYPE X,SUM(PERSONTIMES) VALUE FROM dbo.VIEW_REPORT_PERSONS WHERE CHARGE_TIME>=@begtime AND CHARGE_TIME < @endtime GROUP BY SOURCETYPE
]]>
</GetPersonTimesCollect>
<!-- 年龄分布 -->
<GetPersonTimesForAge>
<![CDATA[
SELECT CASE ISNULL(AGE,'') WHEN '' THEN '未知' ELSE AGE END X,'年龄分布' Y,SUM(PERSONTIMES) VALUE FROM dbo.VIEW_REPORT_PERSONS WHERE CHARGE_TIME>=@begtime AND CHARGE_TIME<@endtime GROUP BY AGE ORDER BY AGE
]]>
</GetPersonTimesForAge>
<!-- 性别分布 -->
<GetPersonTimesForGender>
<![CDATA[
SELECT CASE ISNULL(SEX,'') WHEN '' THEN '未知' ELSE SEX END NAME,SUM(PERSONTIMES) VALUE FROM dbo.VIEW_REPORT_PERSONS WHERE CHARGE_TIME>=@begtime AND CHARGE_TIME<@endtime GROUP BY SEX ORDER BY SEX
]]>
</GetPersonTimesForGender>
<!-- 诊断分布 -->
<GetPersonTimesForDiag>
<![CDATA[
SELECT TOP 10 SOURCETYPE X, DISEASE_NAME Y, SUM(PERSONTIMES) VALUE
FROM [dbo].[VIEW_REPORT_DIAG]
WHERE DISEASE_NAME IS NOT NULL AND SOURCETYPE=@source AND CHARGE_TIME>=@begtime AND CHARGE_TIME<@endtime
GROUP BY SOURCETYPE, DISEASE_NAME
ORDER BY SUM(PERSONTIMES) DESC;
]]>
</GetPersonTimesForDiag>
<!--药品分布-->
<GetPersonTimesForDrug>
<![CDATA[
SELECT TOP 10 SOURCETYPE X, ITEM_NAME Y, SUM(PERSONTIMES) VALUE
FROM [dbo].[VIEW_REPORT_DRUG]
WHERE ITEM_NAME IS NOT NULL AND SOURCETYPE=@source AND CHARGE_TIME>=@begtime AND CHARGE_TIME<@endtime
GROUP BY SOURCETYPE, ITEM_NAME
ORDER BY SUM(PERSONTIMES) DESC;
]]>
</GetPersonTimesForDrug>
</sql>
\ No newline at end of file
using System.Collections.Generic;
public enum Status
{
Ok = 200,
Failed = 501,
Warn = 403,
TokenInvalid = 401,
PramError = 400,
}
public abstract class ApiResponse
{
public ApiResponse() { }
public ApiResponse(Status status)
: this()
{
Status = status;
}
public Status Status { get; set; }
}
public class UnauthorizedResponse : ApiResponse
{
public UnauthorizedResponse()
{
Status = Status.TokenInvalid;
Message = "Token无效";
}
public string Message { get; set; }
}
public class ParameterErrorResponse : ApiResponse
{
public ParameterErrorResponse()
{
Errors = new Dictionary<string, string>();
Status = Status.PramError;
Message = "参数无效";
}
public Dictionary<string, string> Errors { get; set; }
public string Message { get; set; }
public string Instance { get; set; }
}
public class InternalServerErrorResponse : ApiResponse
{
public InternalServerErrorResponse()
{
Status = Status.TokenInvalid;
Message = "Token无效";
}
public object Developer { get; set; }
public string Message { get; set; }
public string Instance { get; set; }
}
public class DomainErrorResponse : ApiResponse
{
public string Message { get; set; }
public string Instance { get; set; }
}
public class OkResponse : ApiResponse
{
public OkResponse(object data)
{
Status = Status.Ok;
Data = data;
}
public object Data { get; set; }
}
public class DoubleSubmitResponse : ApiResponse
{
public DoubleSubmitResponse()
{
Status = Status.Warn;
Message = "网络拥挤,请稍后重试";
}
public string Message { get; set; }
}
\ No newline at end of file
using System;
public class DomainException : Exception
{
public DomainException()
{ }
public DomainException(string message)
: base(message)
{ }
public DomainException(string message, Exception innerException)
: base(message, innerException)
{ }
}
public class TokenErrorException : DomainException
{
public TokenErrorException()
{
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
namespace Health.Infra
{
public class EnumItem
{
public string Name { get; set; }
public int Value { get; set; }
public string Description { get; set; }
}
/// <summary>
/// 枚举类型操作公共类。
/// </summary>
public static class EnumHelper
{
/// <summary>
/// 获取枚举所有成员名称。
/// </summary>
/// <typeparam name="T">枚举类型</typeparam>
public static string[] GetNames<T>()
{
return Enum.GetNames(typeof(T));
}
/// <summary>
/// 返回指定枚举类型的指定值的描述。
/// </summary>
/// <param name="t">枚举类型</param>
/// <param name="v">枚举值</param>
/// <returns></returns>
public static string GetDescription(Enum value)
{
try
{
Type type = value.GetType();
FieldInfo field = type.GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])field.GetCustomAttributes(typeof(DescriptionAttribute), false);
return (attributes.Length > 0) ? attributes[0].Description : string.Empty;
}
catch
{
return string.Empty;
}
}
/// <summary>
/// 获取疾病或药品的Type和Value
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static List<EnumItem> GetItems<T>()
{
var result = new List<EnumItem>();
Type t = typeof(T);
Array arrays = Enum.GetValues(t);
for (int i = 0; i < arrays.LongLength; i++)
{
object item = arrays.GetValue(i);
FieldInfo fieldInfo = item.GetType().GetField(item.ToString());
object[] attribArray = fieldInfo.GetCustomAttributes(false);
if (attribArray == null || attribArray.Length == 0)
{
result.Add(new EnumItem { Name = item.ToString(), Value = Convert.ToInt32(item), Description = item.ToString() });
}
else
{
DescriptionAttribute attrib = (DescriptionAttribute)attribArray[0];
result.Add(new EnumItem { Name = item.ToString(), Value = Convert.ToInt32(item), Description = attrib.Description });
}
}
return result;
}
}
}
public static partial class UtilExtensions
{
}
\ No newline at end of file
using System;
public static partial class UtilExtensions
{
public static long ToTimestamp64(this DateTime dateTime)
{
TimeSpan ts = dateTime - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt64(ts.TotalMilliseconds);
}
public static long ToTimestamp32(this DateTime dateTime)
{
TimeSpan ts = dateTime - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt32(ts.TotalSeconds);
}
}
using System.Collections.Generic;
using System.Linq;
public static partial class UtilExtensions
{
public static SortedDictionary<Tkey, TValue> SortedDictionary<Tkey, TValue>(this Dictionary<Tkey, TValue> pairs)
{
SortedDictionary<Tkey, TValue> dic = new SortedDictionary<Tkey, TValue>();
foreach (var item in pairs)
{
dic.Add(item.Key, item.Value);
}
return dic;
}
public static string JoinUrlArgument<Tkey, TValue>(this SortedDictionary<Tkey, TValue> pairs)
{
return string.Join("&", pairs.Select(w => $"{w.Key}={w.Value}"));
}
}
using System;
using System.Linq;
public static partial class UtilExtensions
{
[System.Diagnostics.DebuggerStepThrough]
public static string GetGenericTypeName(this Type type)
{
var typeName = string.Empty;
if (type.IsGenericType)
{
var genericTypes = string.Join(",", type.GetGenericArguments().Select(t => t.Name).ToArray());
typeName = $"{type.Name.Remove(type.Name.IndexOf('`'))}<{genericTypes}>";
}
else
{
typeName = type.Name;
}
return typeName;
}
[System.Diagnostics.DebuggerStepThrough]
public static string GetGenericTypeName(this object @object)
{
return @object.GetType().GetGenericTypeName();
}
}
using System;
using System.Linq.Expressions;
public static partial class UtilExtensions
{
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.AndAlso<T>(second, Expression.AndAlso);
}
public static Expression<Func<T, bool>> AndIf<T>(this Expression<Func<T, bool>> first, bool condition, Expression<Func<T, bool>> second)
{
if (condition)
return first.AndAlso<T>(second, Expression.AndAlso);
return first;
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.AndAlso<T>(second, Expression.OrElse);
}
public static Expression<Func<T, bool>> OrIf<T>(this Expression<Func<T, bool>> first, bool condition, Expression<Func<T, bool>> second)
{
if (condition)
return first.AndAlso<T>(second, Expression.OrElse);
return first;
}
private static Expression<Func<T, bool>> AndAlso<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2, Func<Expression, Expression, BinaryExpression> func)
{
var parameter = Expression.Parameter(typeof(T));
var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter);
var left = leftVisitor.Visit(expr1.Body);
var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter);
var right = rightVisitor.Visit(expr2.Body);
return Expression.Lambda<Func<T, bool>>(
func(left, right), parameter);
}
private class ReplaceExpressionVisitor : ExpressionVisitor
{
private readonly Expression _oldValue;
private readonly Expression _newValue;
public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)
{
_oldValue = oldValue;
_newValue = newValue;
}
public override Expression Visit(Expression node)
{
if (node == _oldValue)
return _newValue;
return base.Visit(node);
}
}
public static class LinqBuilder
{
/// <summary>
/// 默认True条件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression<Func<T, bool>> True<T>() { return f => true; }
/// <summary>
/// 默认False条件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression<Func<T, bool>> False<T>() { return f => false; }
}
}
\ No newline at end of file
public static partial class UtilExtensions
{
}
\ No newline at end of file
using System;
using System.Security.Cryptography;
using System.Text;
public static partial class UtilExtensions
{
public static string RemoveLineBreak(this string text)
{
return text.Replace("\n", "");
}
public static string RemoveEnter(this string text)
{
return text.Replace("\r", "");
}
public static string Md5Encrypt(this string text, string charset = "utf-8")
{
var sb = new StringBuilder(32);
MD5 md5 = new MD5CryptoServiceProvider();
var bytes = md5.ComputeHash(Encoding.GetEncoding(charset).GetBytes(text));
foreach (var t1 in bytes)
{
sb.Append(t1.ToString("x").PadLeft(2, '0'));
}
return sb.ToString();
}
/// <summary>
/// 分隔 移除空项
/// </summary>
/// <param name="text"></param>
/// <param name="separator"></param>
/// <returns></returns>
public static string[] SplitRemoveEmpty(this string text, params string[] separator)
{
if (string.IsNullOrEmpty(text))
return Array.Empty<string>();
return text.Split(separator, StringSplitOptions.RemoveEmptyEntries);
}
/// <summary>
/// 转换Int32数组
/// </summary>
/// <param name="array"></param>
/// <returns></returns>
public static int[] ToInt32Arrary(this string[] array)
{
return Array.ConvertAll(array, t => Convert.ToInt32(t));
}
/// <summary>
/// 不区分大小写比较
/// </summary>
/// <param name="text"></param>
/// <param name="compare"></param>
/// <returns></returns>
public static bool EqualsIgnoreCase(this string text, string compare)
{
return text.Equals(compare, StringComparison.InvariantCultureIgnoreCase);
}
/// <summary>
/// 不区分大小写替换
/// </summary>
/// <param name="text"></param>
/// <param name="compare"></param>
/// <returns></returns>
public static string ReplaceIgnoreCase(this string text, string oldValue, string newValue)
{
return text.Replace(oldValue, newValue, StringComparison.OrdinalIgnoreCase);
}
}
\ No newline at end of file
namespace Health.Infra
{
public interface IJsonConverter
{
/// <summary>
/// 序列化
/// </summary>
/// <param name="object"></param>
/// <returns></returns>
string Serialize(object @object);
/// <summary>
/// 反序列化
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="json"></param>
/// <returns></returns>
T Deserialize<T>(string json);
}
}
using System.Collections.Generic;
using System.Security.Claims;
namespace Health.Infra
{
public interface IUserIdentity
{
int UserId { get; }
IEnumerable<Claim> Claims { get; }
bool TryClaim(string type, out string value);
bool IsAuthenticated { get; }
}
}
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using System;
namespace Health.Infra
{
public class IsoDateTimeConverterContent : IsoDateTimeConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is DateTime)
{
DateTime dateTime = (DateTime)value;
if (dateTime == default(DateTime)
|| dateTime == DateTime.MinValue
|| dateTime.ToString("yyyy-MM-dd") == "1970-01-01"
|| dateTime.ToString("yyyy-MM-dd") == "1900-01-01")
{
writer.WriteValue("");
return;
}
}
base.WriteJson(writer, value, serializer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return base.ReadJson(reader, objectType, existingValue, serializer);
}
}
public class LowercaseContractResolver : DefaultContractResolver
{
protected override string ResolvePropertyName(string propertyName)
{
return propertyName.ToLower();
}
}
public class UppercaseContractResolver : DefaultContractResolver
{
protected override string ResolvePropertyName(string propertyName)
{
return propertyName.ToUpper();
}
}
}
using System.Security.Cryptography;
using System.Text;
namespace Health.Infra
{
public class Md5Util
{
public static string Encrypt(string @string)
{
using (MD5 md5 = MD5.Create())
{
byte[] buffer = Encoding.Default.GetBytes(@string);
byte[] md5buffer = md5.ComputeHash(buffer);
StringBuilder builder = new StringBuilder();
foreach (byte b in md5buffer)
{
builder.Append(b.ToString("x2"));
}
return builder.ToString();
}
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
public class ReportData
{
public ReportData()
: this("")
{
}
public ReportData(string title)
{
Title = title;
}
/// <summary>
///
/// </summary>
public Nullable<int> ChartType { get; set; }
/// <summary>
/// 报表标题
/// </summary>
public string Title { get; set; }
/// <summary>
/// X轴标题
/// </summary>
public string XTitle { get; set; }
/// <summary>
/// X轴单位
/// </summary>
public string XUnit { get; set; }
/// <summary>
/// Y轴标题
/// </summary>
public string YTitle { get; set; }
/// <summary>
/// Y轴单位
/// </summary>
public string YUnit { get; set; }
/// <summary>
/// 值标题
/// </summary>
public string VTitle { get; set; }
/// <summary>
/// 值单位
/// </summary>
public string VUnit { get; set; }
/// <summary>
/// name标题
/// </summary>
public string NTitle { get; set; }
/// <summary>
/// name单位
/// </summary>
public string NUnit { get; set; }
/// <summary>
/// 图表说明
/// </summary>
public string Formula { get; set; }
/// <summary>
/// 1表示需要进行小于百分2的类型进行合并
/// </summary>
public Nullable<int> DataType { get; set; }
/// <summary>
/// 图标value过滤执值
/// </summary>
public Nullable<decimal> FilterValue { get; set; }
/// <summary>
/// 图表数据
/// </summary>
public IEnumerable<ChartData> ChartData { get; set; } = new List<ChartData>();
}
/// <summary>
/// 图表
/// </summary>
public class ChartData
{
/// <summary>
/// X轴内容
/// </summary>
public string X { get; set; }
/// <summary>
/// Y轴内容
/// </summary>
public string Y { get; set; }
/// <summary>
/// 分类
/// </summary>
public string Name { get; set; }
/// <summary>
/// 值
/// </summary>
public Double Value { get; set; }
/// <summary>
/// 总量
/// </summary>
public Double? Total { get; set; }
/// <summary>
/// ChartData 类型标签
/// </summary>
public string Type { get; set; }
}

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30517.126
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QueryPlatform.Api", "Health.Api\QueryPlatform.Api.csproj", "{7D7E81D8-76AC-4B16-9F93-B4689BBC423E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QueryPlatform.Infra", "Health.Infra\QueryPlatform.Infra.csproj", "{A4750395-66B7-4F21-B87B-6B67F5F598BF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7D7E81D8-76AC-4B16-9F93-B4689BBC423E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7D7E81D8-76AC-4B16-9F93-B4689BBC423E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7D7E81D8-76AC-4B16-9F93-B4689BBC423E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7D7E81D8-76AC-4B16-9F93-B4689BBC423E}.Release|Any CPU.Build.0 = Release|Any CPU
{A4750395-66B7-4F21-B87B-6B67F5F598BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A4750395-66B7-4F21-B87B-6B67F5F598BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A4750395-66B7-4F21-B87B-6B67F5F598BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A4750395-66B7-4F21-B87B-6B67F5F598BF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E96E5CF7-3282-4170-8C49-9B7C016D15B5}
EndGlobalSection
EndGlobal
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