Commit 1fb74544 by wyc

简单查询

parent 23a71138
......@@ -8,11 +8,13 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Performance.DtoModels;
using Performance.DtoModels.AppSettings;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Services;
namespace Performance.Api.Controllers
......@@ -20,19 +22,20 @@ namespace Performance.Api.Controllers
[Route("api/[controller]")]
public class AccountController : Controller
{
private UserService _userService;
private RoleService _roleService;
private IMemoryCache _memoryCache;
private Application _options;
private ClaimService _claim;
private HospitalService _hospitalService;
private readonly UserService _userService;
private readonly RoleService _roleService;
private readonly IMemoryCache _memoryCache;
private readonly Application _options;
private readonly ClaimService _claim;
private readonly HospitalService _hospitalService;
private readonly ILogger<AppController> _logger;
public AccountController(UserService userService,
HospitalService hospitalService,
RoleService roleService,
IMemoryCache memoryCache,
IOptions<Application> options,
ClaimService claim)
ClaimService claim, ILogger<AppController> logger)
{
_userService = userService;
_roleService = roleService;
......@@ -40,6 +43,7 @@ public class AccountController : Controller
_hospitalService = hospitalService;
_options = options.Value;
_claim = claim;
_logger = logger;
}
/// <summary>
......@@ -189,6 +193,8 @@ public ApiResponse SelfInfo()
int[] roleArray = UnitTypeUtil.Maps.Keys.ToArray();
user.IsAgainAdmin = user.Role != null ? roleArray.Contains(user.Role.First().Type ?? 0) : false;
_logger.LogInformation($"查询个人信息二次分配角色映射表【{JsonHelper.Serialize(roleArray)}】");
_logger.LogInformation($"查询个人信息分配角色【{JsonHelper.Serialize(user.Role)}】");
return new ApiResponse(ResponseType.OK, user);
}
......@@ -352,7 +358,8 @@ public ApiResponse SelfInfos([FromBody] UserRequest request)
{
user.IsInitialPassword = (int)InitialPassword.修改;
}
_logger.LogInformation($"查询用户信息二次分配角色映射表【{JsonHelper.Serialize(roleArray)}】");
_logger.LogInformation($"查询用户信息分配角色【{JsonHelper.Serialize(user.Role)}】");
return new ApiResponse(ResponseType.OK, user);
}
......
using MassTransit.Internals.Extensions;
using Masuit.Tools;
using Masuit.Tools.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Performance.DtoModels;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Services;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using ExcelColumn = Performance.Infrastructure.ExcelColumn;
namespace Performance.Api.Controllers
{
/// <summary>
/// 可配置数据查询
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class LowProcController : Controller
{
private readonly LowProcService _services;
private readonly ClaimService _claim;
private readonly UserService _userService;
private readonly RoleService _roleService;
private readonly ILogger<AppController> _logger;
/// ctor
public LowProcController(LowProcService services, ClaimService claim, UserService userService, RoleService roleService, ILogger<AppController> logger)
{
_services = services;
_claim = claim;
_userService = userService;
_roleService = roleService;
_logger = logger;
}
/// <summary>
/// 扩展查询
/// </summary>
/// <param name="title">扩展查询名</param>
/// <param name="paged"></param>
/// <returns></returns>
[HttpGet("list")]
[ProducesResponseType(typeof(PagedList<low_proc>), StatusCodes.Status200OK)]
public ApiResponse<object> GetListAsync([FromQuery] string? title, [FromQuery] PagedQueryRequest? paged)
{
var proc = _services.GetListAsync(title, paged?.Page ?? 1, paged?.Size ?? 20);
return new ApiResponse<object>(ResponseType.OK, proc);
}
/// <summary>
/// 新增扩展查询记录
/// </summary>
/// <param name="procDto"></param>
/// <returns></returns>
[HttpPost("add")]
public async Task<ApiResponse> AddAsync([FromBody] LowProcRequest procDto)
{
var userid = _claim.GetUserId();
await _services.AddAsync(procDto, userid);
return new ApiResponse(ResponseType.OK, "添加成功");
}
/// <summary>
/// 修改扩展查询记录
/// </summary>
/// <param name="procId"></param>
/// <param name="procDto"></param>
/// <returns></returns>
[HttpPost("update")]
public async Task<ApiResponse> UpdateAsync([FromQuery, Required] long procId, [FromBody] LowProcRequest procDto)
{
var userid = _claim.GetUserId();
await _services.UpdateAsync(procId, userid, procDto);
return new ApiResponse(ResponseType.OK, "修改成功");
}
/// <summary>
/// 删除扩展查询记录
/// </summary>
/// <param name="procIds"></param>
/// <returns></returns>
[HttpPost("delete")]
public ApiResponse DeleteAsync([FromBody] long[] procIds)
{
_services.DeleteAsync(procIds);
return new ApiResponse(ResponseType.OK, "删除成功");
}
/// <summary>
/// 扩展数据查询
/// </summary>
/// <param name="procId"></param>
/// <param name="allotId"></param>
/// <param name="paged"></param>
/// <param name="filters"></param>
/// <returns></returns>
[HttpPost(template: "query/datum")]
[ResponseCache(VaryByHeader = "User-Agent", Duration = 10)]
[ProducesResponseType(typeof(List<DashboardResponse>), StatusCodes.Status200OK)]
public async Task<ApiResponse<object>> GetDatumAsync([FromQuery, Required] long procId, [FromQuery] string? allotId, [FromQuery] PagedQueryRequest? paged, [FromBody] List<DynamicQuery> filters)
{
var filteredQueries = filters.Where(q => !string.IsNullOrEmpty(q.Value)).ToList();
long allotIdValue = long.TryParse(allotId, out var result) ? result : 0;
var args = Args(allotIdValue, paged?.Page ?? 1, paged?.Size ?? 20);
var res = await _services.GetDatumAsync(procId, filteredQueries, paged?.Page ?? 1, paged?.Size ?? 20, args);
foreach (var item in res.Columns)
{
item.Field = item.Field.ToLower();
}
return new ApiResponse<object>(ResponseType.OK, res);
}
private Dictionary<string, object> Args(long allotId, int page, int size)
{
var userid = _claim.GetUserId();
var userClaim = _claim.GetUserClaim();
var user = _userService.GetUser(userid);
user.Role = _roleService.GetUserRole(user.UserID);
var unitTypes = new List<string>();
if (user.Role.Any() && user.Role.First().Type.HasValue && UnitTypeUtil.Maps.ContainsKey(user.Role.First().Type.Value))
unitTypes = UnitTypeUtil.Maps[user.Role.First().Type.Value].ToList();
var unitType = string.Join(",", unitTypes);
var args = userClaim.ToDictionary(c => c.Type, c => (object)c.Value);
args.AddOrUpdate("unittype", unitType, unitType);
args.AddOrUpdate("allotid", allotId, allotId);
args.AddOrUpdate("userid", userid, userid);
args.AddOrUpdate("rolename", user.Role.First().RoleName, user.Role.First().RoleName);
var userInfo = JsonConvert.SerializeObject(args, Tools.GetJsonSerializerSettings()) ?? "{}";
args.AddOrUpdate("userinfo", userInfo, userInfo);
args.AddOrUpdate("page", page, page);
args.AddOrUpdate("size", size, size);
return args;
}
/// <summary>
/// 扩展数据查询导出
/// </summary>
/// <param name="procId"></param>
/// <param name="allotId"></param>
/// <param name="filters"></param>
/// <returns></returns>
[HttpPost(template: "query/datum/export")]
public async Task<IActionResult> GetDatumExportAsync([FromQuery, Required] long procId, [FromQuery] string? allotId, [FromBody] List<DynamicQuery> filters)
{
var filteredQueries = filters.Where(q => !string.IsNullOrEmpty(q.Value)).ToList();
long allotIdValue = long.TryParse(allotId, out var result) ? result : 0;
var lowProc = await _services.GetAsync(procId)
?? throw new PerformanceException("查询配置信息不存在");
var args = Args(allotIdValue, 1, int.MaxValue);
var res = await _services.GetDatumAsync(procId, filteredQueries, 1, int.MaxValue, args);
var filePath = Path.Combine(Tools.Path.Download, $"{lowProc.Title}.{Guid.NewGuid():N}.xlsx");
var rows = Tools.MapDictionary(res.Data);
var columns = res.Columns?.Select(w => new ExcelColumn(w.Title, w.Field)).ToList() ?? new List<ExcelColumn>();
Tools.Export(filePath, new ExcelExportOption() { Name = lowProc.Title, Rows = rows, Columns = columns, Aggregate = true });
var memoryStream = new MemoryStream();
using (var stream = new FileStream(filePath, FileMode.Open))
{
await stream.CopyToAsync(memoryStream);
}
memoryStream.Seek(0, SeekOrigin.Begin);
var provider = new FileExtensionContentTypeProvider();
var memi = provider.Mappings[".xlsx"];
var fileInfo = new FileInfo(filePath);
return File(memoryStream, memi, Path.GetFileName(fileInfo.Name));
}
}
}
using System;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using NLog.Web;
using System;
using Yitter.IdGenerator;
namespace Performance.Api
{
......@@ -11,6 +12,8 @@ public class Program
{
public static void Main(string[] args)
{
var options = new IdGeneratorOptions(1);
YitIdHelper.SetIdGenerator(options);
var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
FunctionLimit.Init(logger);
try
......
......@@ -2263,6 +2263,63 @@
<param name="request"></param>
<returns></returns>
</member>
<member name="T:Performance.Api.Controllers.LowProcController">
<summary>
可配置数据查询
</summary>
</member>
<member name="M:Performance.Api.Controllers.LowProcController.#ctor(Performance.Services.LowProcService,Performance.Api.ClaimService,Performance.Services.UserService,Performance.Services.RoleService,Microsoft.Extensions.Logging.ILogger{Performance.Api.Controllers.AppController})">
ctor
</member>
<member name="M:Performance.Api.Controllers.LowProcController.GetListAsync(System.String,Performance.DtoModels.PagedQueryRequest)">
<summary>
扩展查询
</summary>
<param name="title">扩展查询名</param>
<param name="paged"></param>
<returns></returns>
</member>
<member name="M:Performance.Api.Controllers.LowProcController.AddAsync(Performance.DtoModels.LowProcRequest)">
<summary>
新增扩展查询记录
</summary>
<param name="procDto"></param>
<returns></returns>
</member>
<member name="M:Performance.Api.Controllers.LowProcController.UpdateAsync(System.Int64,Performance.DtoModels.LowProcRequest)">
<summary>
修改扩展查询记录
</summary>
<param name="procId"></param>
<param name="procDto"></param>
<returns></returns>
</member>
<member name="M:Performance.Api.Controllers.LowProcController.DeleteAsync(System.Int64[])">
<summary>
删除扩展查询记录
</summary>
<param name="procIds"></param>
<returns></returns>
</member>
<member name="M:Performance.Api.Controllers.LowProcController.GetDatumAsync(System.Int64,System.Nullable{System.Int64},Performance.DtoModels.PagedQueryRequest,System.Collections.Generic.List{Performance.DtoModels.DynamicQuery})">
<summary>
扩展数据查询
</summary>
<param name="procId"></param>
<param name="allotId"></param>
<param name="paged"></param>
<param name="filters"></param>
<returns></returns>
</member>
<member name="M:Performance.Api.Controllers.LowProcController.GetDatumExportAsync(System.Int64,System.String,System.Collections.Generic.List{Performance.DtoModels.DynamicQuery})">
<summary>
扩展数据查询导出
</summary>
<param name="procId"></param>
<param name="allotId"></param>
<param name="filters"></param>
<returns></returns>
</member>
<member name="M:Performance.Api.Controllers.MenuController.MenuList">
<summary>
用户登录后菜单列表
......
......@@ -111,6 +111,21 @@
<param name="input"></param>
<returns></returns>
</member>
<member name="T:Performance.DtoModels.DynamicQuery">
<summary>
动态查询
</summary>
</member>
<member name="P:Performance.DtoModels.DynamicQuery.Field">
<summary>
字段名
</summary>
</member>
<member name="P:Performance.DtoModels.DynamicQuery.Value">
<summary>
文本
</summary>
</member>
<member name="T:Performance.DtoModels.SmsCodeType">
<summary> 验证码类型 </summary>
</member>
......@@ -2752,6 +2767,35 @@
登录类型 1 手机号登录 2 账号登录
</summary>
</member>
<member name="T:Performance.DtoModels.LowProcRequest">
<param name="Title">存储过程名称</param>
<param name="Script">SQL</param>
<param name="Remark">备注</param>
<param name="AllotLimit">绩效ID限制</param>
<param name="DataPermissionLimit">数据权限限制 0 不限制 1 限制</param>
</member>
<member name="M:Performance.DtoModels.LowProcRequest.#ctor(System.String,System.String,System.String,System.Boolean,System.Boolean)">
<param name="Title">存储过程名称</param>
<param name="Script">SQL</param>
<param name="Remark">备注</param>
<param name="AllotLimit">绩效ID限制</param>
<param name="DataPermissionLimit">数据权限限制 0 不限制 1 限制</param>
</member>
<member name="P:Performance.DtoModels.LowProcRequest.Title">
<summary>存储过程名称</summary>
</member>
<member name="P:Performance.DtoModels.LowProcRequest.Script">
<summary>SQL</summary>
</member>
<member name="P:Performance.DtoModels.LowProcRequest.Remark">
<summary>备注</summary>
</member>
<member name="P:Performance.DtoModels.LowProcRequest.AllotLimit">
<summary>绩效ID限制</summary>
</member>
<member name="P:Performance.DtoModels.LowProcRequest.DataPermissionLimit">
<summary>数据权限限制 0 不限制 1 限制</summary>
</member>
<member name="P:Performance.DtoModels.ModItemRequest.ModuleId">
<summary>
......@@ -2810,6 +2854,21 @@
<member name="P:Performance.DtoModels.SpecialListRequest.Items">
<summary> 特殊考核项 </summary>
</member>
<member name="T:Performance.DtoModels.PagedQueryRequest">
<summary>
分页查询参数
</summary>
</member>
<member name="P:Performance.DtoModels.PagedQueryRequest.Page">
<summary>
页码
</summary>
</member>
<member name="P:Performance.DtoModels.PagedQueryRequest.Size">
<summary>
行数
</summary>
</member>
<member name="P:Performance.DtoModels.PasswordRequest.OldPwd">
<summary>
原始密码
......@@ -4277,6 +4336,117 @@
医院总收支结余
</summary>
</member>
<member name="T:Performance.DtoModels.ColumnResponse">
<inheritdoc/>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.ColId">
<inheritdoc/>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.ParentId">
<summary>
父菜单ID
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.Key">
<summary>
识别关键字(菜单KEY)
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.OrigName">
<summary>
系统名称
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.Field">
<summary>
字段名
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.Title">
<summary>
标题
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.Width">
<summary>
宽度
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.Resizable">
<summary>
拖动列宽(1 允许 0 禁止)
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.Visible">
<summary>
显示(1 显示 0 隐藏)
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.Filter">
<summary>
筛选(1 筛选 0 禁止)
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.Fixed">
<summary>
列固定(left:固定左侧 right:固定右侧)
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.Align">
<summary>
列对齐(left:左对齐 center:居中对齐 right:右对齐)
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.Formatter">
<summary>
格式化
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.Sort">
<summary>
列排序
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.Sortable">
<summary>
列排序(1 允许 0 禁止)
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.BackColor">
<summary>
背景色
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.EnumName">
<summary>
数据枚举
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.Attach">
<summary>
附加信息(无固定用途,慎重使用)
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.AttachParams">
<summary>
附加信息(无固定用途,慎重使用)
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.AttachStatus">
<summary>
附加信息(无固定用途,慎重使用)
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.AttachOptions">
<summary>
附加信息(无固定用途,慎重使用)
</summary>
</member>
<member name="P:Performance.DtoModels.ColumnResponse.Children">
<summary>
子集
</summary>
</member>
<member name="P:Performance.DtoModels.ComputeResponse.Source">
<summary>
来源
......@@ -4422,6 +4592,59 @@
0 未审核 1 部分审核 2 全部审核
</summary>
</member>
<member name="T:Performance.DtoModels.DashboardResponse">
大屏对象
</member>
<member name="P:Performance.DtoModels.DashboardResponse.Id">
<summary>
Id
</summary>
</member>
<member name="P:Performance.DtoModels.DashboardResponse.MenuKey">
<summary>
菜单KEY
</summary>
</member>
<member name="P:Performance.DtoModels.DashboardResponse.Title">
<summary>
标题
</summary>
</member>
<member name="P:Performance.DtoModels.DashboardResponse.Name">
<summary>
数据来源
</summary>
</member>
<member name="P:Performance.DtoModels.DashboardResponse.Width">
<summary>
宽度
</summary>
</member>
<member name="P:Performance.DtoModels.DashboardResponse.Height">
<summary>
高度
</summary>
</member>
<member name="P:Performance.DtoModels.DashboardResponse.Options">
<summary>
自定义设置
</summary>
</member>
<member name="P:Performance.DtoModels.DashboardResponse.Remark">
<summary>
备注
</summary>
</member>
<member name="P:Performance.DtoModels.DashboardResponse.Sort">
<summary>
图表位置
</summary>
</member>
<member name="P:Performance.DtoModels.DashboardResponse.Data">
<summary>
数据
</summary>
</member>
<member name="P:Performance.DtoModels.DeptDataDetails`1.Pandect">
<summary> 概览</summary>
</member>
......
......@@ -5758,6 +5758,88 @@
1、绩效生成日志 2、绩效提取日志 3、绩效提取进度
</summary>
</member>
<member name="T:Performance.EntityModels.low_proc">
<summary>
配置表 -- 表名
</summary>
</member>
<member name="P:Performance.EntityModels.low_proc.ProcId">
<summary>
Desc:
Default:
Nullable:False
</summary>
</member>
<member name="P:Performance.EntityModels.low_proc.Title">
<summary>
Desc:标题
Default:
Nullable:False
</summary>
</member>
<member name="P:Performance.EntityModels.low_proc.Script">
<summary>
Desc:执行脚本
Default:
Nullable:True
</summary>
</member>
<member name="P:Performance.EntityModels.low_proc.Describe">
<summary>
Desc:描述
Default:
Nullable:True
</summary>
</member>
<member name="P:Performance.EntityModels.low_proc.Remark">
<summary>
Desc:备注
Default:
Nullable:True
</summary>
</member>
<member name="P:Performance.EntityModels.low_proc.CreateBy">
<summary>
Desc:创建人
Default:0
Nullable:False
</summary>
</member>
<member name="P:Performance.EntityModels.low_proc.CreateTime">
<summary>
Desc:创建时间
Default:CURRENT_TIMESTAMP
Nullable:False
</summary>
</member>
<member name="P:Performance.EntityModels.low_proc.UpdateBy">
<summary>
Desc:最后修改人
Default:0
Nullable:False
</summary>
</member>
<member name="P:Performance.EntityModels.low_proc.UpdateTime">
<summary>
Desc:修改时间
Default:CURRENT_TIMESTAMP
Nullable:False
</summary>
</member>
<member name="P:Performance.EntityModels.low_proc.RowVersion">
<summary>
Desc:数据版本号
Default:0
Nullable:False
</summary>
</member>
<member name="P:Performance.EntityModels.low_proc.Deleted">
<summary>
Desc:删除标记(1 删除 0 未删)
Default:true
Nullable:False
</summary>
</member>
<member name="T:Performance.EntityModels.mod_dic">
<summary>
部分公共数据抽取SQL
......
......@@ -296,6 +296,7 @@ public AutoMapperConfigs()
CreateMap<AttendanceData, per_attendance>().ReverseMap();
CreateMap<AttendanceVacationData, per_attendance_vacation>().ReverseMap();
CreateMap<LowProcRequest, low_proc>().ReverseMap();
}
}
}
namespace Performance.DtoModels
{
/// <summary>
/// 动态查询
/// </summary>
public class DynamicQuery
{
/// <summary>
/// 字段名
/// </summary>
public string Field { get; set; } = string.Empty;
/// <summary>
/// 文本
/// </summary>
public string Value { get; set; } = string.Empty;
}
}
\ No newline at end of file
......@@ -303,5 +303,12 @@ public enum CustomTableLimitation
无限制 = 1,
}
[Description(description: "格式类型")]
public enum Formatter
{
text,
numeric,
tag,
}
}
}
namespace Performance.DtoModels
{
/// <param name="Title">存储过程名称</param>
/// <param name="Script">SQL</param>
/// <param name="Remark">备注</param>
/// <param name="AllotLimit">绩效ID限制</param>
/// <param name="DataPermissionLimit">数据权限限制 0 不限制 1 限制</param>
public record LowProcRequest(string Title, string Script, string? Remark, bool AllotLimit, bool DataPermissionLimit);
}
namespace Performance.DtoModels
{
/// <summary>
/// 分页查询参数
/// </summary>
public class PagedQueryRequest
{
/// <summary>
/// 页码
/// </summary>
public int? Page { get; set; } = 1;
/// <summary>
/// 行数
/// </summary>
public int? Size { get; set; } = 20;
}
}
using System;
using System.Collections.Generic;
namespace Performance.DtoModels
{
/// <inheritdoc/>
public class ColumnResponse : IChildren<ColumnResponse>
{
/// <inheritdoc/>
public long ColId { get; set; }
/// <summary>
/// 父菜单ID
/// </summary>
public long ParentId { get; set; }
/// <summary>
/// 识别关键字(菜单KEY)
/// </summary>
public string Key { get; set; } = string.Empty;
/// <summary>
/// 系统名称
/// </summary>
public string OrigName { get; set; } = string.Empty;
/// <summary>
/// 字段名
/// </summary>
public string Field { get; set; } = string.Empty;
/// <summary>
/// 标题
/// </summary>
public string Title { get; set; } = string.Empty;
/// <summary>
/// 宽度
/// </summary>
public double? Width { get; set; }
/// <summary>
/// 拖动列宽(1 允许 0 禁止)
/// </summary>
public bool? Resizable { get; set; }
/// <summary>
/// 显示(1 显示 0 隐藏)
/// </summary>
public bool? Visible { get; set; }
/// <summary>
/// 筛选(1 筛选 0 禁止)
/// </summary>
public bool? Filter { get; set; }
/// <summary>
/// 列固定(left:固定左侧 right:固定右侧)
/// </summary>
public string? Fixed { get; set; }
/// <summary>
/// 列对齐(left:左对齐 center:居中对齐 right:右对齐)
/// </summary>
public string? Align { get; set; }
/// <summary>
/// 格式化
/// </summary>
public string? Formatter { get; set; }
/// <summary>
/// 列排序
/// </summary>
public int? Sort { get; set; }
/// <summary>
/// 列排序(1 允许 0 禁止)
/// </summary>
public bool? Sortable { get; set; }
/// <summary>
/// 背景色
/// </summary>
public string? BackColor { get; set; }
/// <summary>
/// 数据枚举
/// </summary>
public string? EnumName { get; set; }
/// <summary>
/// 附加信息(无固定用途,慎重使用)
/// </summary>
public string? Attach { get; set; }
/// <summary>
/// 附加信息(无固定用途,慎重使用)
/// </summary>
public string? AttachParams { get; set; }
/// <summary>
/// 附加信息(无固定用途,慎重使用)
/// </summary>
public string AttachStatus { get; set; } = string.Empty;
/// <summary>
/// 附加信息(无固定用途,慎重使用)
/// </summary>
public object? AttachOptions { get; set; }
/// <summary>
/// 子集
/// </summary>
public IEnumerable<ColumnResponse> Children { get; set; } = new HashSet<ColumnResponse>();
}
}
\ No newline at end of file
using System;
namespace Performance.DtoModels
{
/// 大屏对象
public class DashboardResponse
{
/// <summary>
/// Id
/// </summary>
public long Id { get; set; }
/// <summary>
/// 菜单KEY
/// </summary>
public string MenuKey { get; set; }
/// <summary>
/// 标题
/// </summary>
public string Title { get; set; }
/// <summary>
/// 数据来源
/// </summary>
public string Name { get; set; }
/// <summary>
/// 宽度
/// </summary>
public string Width { get; set; }
/// <summary>
/// 高度
/// </summary>
public string Height { get; set; }
/// <summary>
/// 自定义设置
/// </summary>
public string Options { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
/// <summary>
/// 图表位置
/// </summary>
public int Sort { get; set; }
/// <summary>
/// 数据
/// </summary>
public object Data { get; set; }
}
}
......@@ -284,6 +284,7 @@ public PerformanceDbContext(DbContextOptions<PerformanceDbContext> options)
public virtual DbSet<per_assess_scheme_items> per_assess_scheme_items { get; set; }
/// <summary>被考核对象</summary>
public virtual DbSet<per_assess_scheme_target> per_assess_scheme_target { get; set; }
public virtual DbSet<low_proc> low_proc { get; set; }
/// <summary>
/// 在这个方法中,你可以配置实体类型之间的关系、数据库表的映射以及其他一些高级配置。
/// 这是 Entity Framework Core 中的一个重要方法,在派生自 DbContext 的类中重写它以定义数据模型
......
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Performance.EntityModels
{
/// <summary>
/// 配置表 -- 表名
/// </summary>
[Table("low_proc")]
public class low_proc
{
/// <summary>
/// Desc:
/// Default:
/// Nullable:False
/// </summary>
[Key]
public long ProcId { get; set; }
/// <summary>
/// Desc:标题
/// Default:
/// Nullable:False
/// </summary>
public string Title { get; set; } = null!;
/// <summary>
/// Desc:执行脚本
/// Default:
/// Nullable:True
/// </summary>
public string? Script { get; set; }
/// <summary>
/// Desc:描述
/// Default:
/// Nullable:True
/// </summary>
public string? Describe { get; set; }
/// <summary>
/// Desc:备注
/// Default:
/// Nullable:True
/// </summary>
public string? Remark { get; set; }
/// <summary>
/// Desc:创建人
/// Default:0
/// Nullable:False
/// </summary>
public long CreateBy { get; set; }
/// <summary>
/// Desc:创建时间
/// Default:CURRENT_TIMESTAMP
/// Nullable:False
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// Desc:最后修改人
/// Default:0
/// Nullable:False
/// </summary>
public long UpdateBy { get; set; }
/// <summary>
/// Desc:修改时间
/// Default:CURRENT_TIMESTAMP
/// Nullable:False
/// </summary>
public DateTime UpdateTime { get; set; }
/// <summary>
/// Desc:数据版本号
/// Default:0
/// Nullable:False
/// </summary>
public long RowVersion { get; set; }
/// <summary>
/// Desc:删除标记(1 删除 0 未删)
/// Default:true
/// Nullable:False
/// </summary>
public bool Deleted { get; set; }
}
}
......@@ -8,7 +8,16 @@ public static partial class UtilExtensions
{
return first.AndAlso<T>(second, Expression.AndAlso);
}
public static Expression<Func<T, bool>> AndIf<T>(this Expression<Func<T, bool>> source, bool condition, Expression<Func<T, bool>> predicate)
{
if (condition)
{
var invokedExpr = Expression.Invoke(predicate, source.Parameters);
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(source.Body, invokedExpr), source.Parameters);
}
return source;
}
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);
......
using Masuit.Tools.Models;
using System.Collections.Generic;
namespace Performance.Infrastructure.Models
{
/// <summary>
/// 分页
/// </summary>
/// <typeparam name="TColumn"></typeparam>
/// <typeparam name="TData"></typeparam>
public class PagedList<TData, TColumn> : PagedList<TData> where TColumn : class
{
/// <summary>
/// 列头
/// </summary>
public ICollection<TColumn>? Columns { get; set; }
/// <inheritdoc/>
public PagedList(PagedList<TData> paged, List<TColumn>? columns = null)
: this(paged.Data, paged.CurrentPage, paged.PageSize, paged.TotalCount, columns)
{
}
/// <inheritdoc/>
public PagedList(List<TData> items, int page, int size, int count, List<TColumn>? columns = null)
: base(items, page, size, count)
{
Columns = columns;
}
}
/// <summary>
/// 分页
/// </summary>
/// <typeparam name="TColumn"></typeparam>
/// <typeparam name="TData"></typeparam>
/// <typeparam name="TTotal"></typeparam>
public class PagedList<TData, TColumn, TTotal> : PagedList<TData, TColumn> where TColumn : class
{
/// <summary>
/// 汇总
/// </summary>
public ICollection<TTotal>? Totals { get; set; }
/// <inheritdoc/>
public PagedList(PagedList<TData> paged, List<TColumn>? columns = null, List<TTotal>? total = null)
: this(paged.Data, paged.CurrentPage, paged.PageSize, paged.TotalCount, columns, total)
{
}
/// <inheritdoc/>
public PagedList(List<TData> items, int page, int size, int count, List<TColumn>? columns = null, List<TTotal>? total = null)
: base(items, page, size, count, columns)
{
Totals = total;
}
}
}
using NLog.Fluent;
using OfficeOpenXml;
using OfficeOpenXml.Style;
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
namespace Performance.Infrastructure
{
public static partial class Tools
{
#region Read Excel
/// <summary>
/// 按工作表名称读取Excel
/// </summary>
/// <param name="package"></param>
/// <param name="name"></param>
/// <param name="startRow"></param>
/// <param name="startCol"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static DataTable Read(this ExcelPackage package, string name, int startRow = 1, int startCol = 1)
{
if (package is null)
throw new ArgumentNullException(nameof(package));
if (!package.Workbook.Worksheets.Any(w => w.Name == name))
return package.Read(0);
var worksheet = package.Workbook.Worksheets[name];
return Read(worksheet, startRow, startCol);
}
/// <summary>
/// 按工作表索引读取Excel
/// </summary>
/// <param name="package"></param>
/// <param name="index"></param>
/// <param name="startRow"></param>
/// <param name="startCol"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static DataTable Read(this ExcelPackage package, int index, int startRow = 1, int startCol = 1)
{
if (package is null)
throw new ArgumentNullException(nameof(package));
var worksheet = package.Workbook.Worksheets[index];
return Read(worksheet, startRow, startCol);
}
/// <summary>
/// 读取工作表
/// </summary>
/// <param name="ws"></param>
/// <param name="startRow"></param>
/// <param name="startCol"></param>
/// <returns></returns>
/// <exception cref="PerformanceException"></exception>
public static DataTable Read(this ExcelWorksheet ws, int startRow = 1, int startCol = 1)
{
try
{
ws.View.UnFreezePanes();
if (ws.Cells == null || ws.Dimension == null)
{
// 如果 ExcelWorksheet 为空,直接返回一个空的 DataTable
return new DataTable();
}
var table = new DataTable();
foreach (var firstRowCell in ws.Cells[startRow, startCol, 1, ws.Dimension.End.Column])
{
var name = !string.IsNullOrEmpty(firstRowCell.Text) ? firstRowCell.Text : $"Column {firstRowCell.Start.Column}";
if (!string.IsNullOrEmpty(name) && table.Columns.Contains(name))
{
throw new InvalidOperationException($"重复列名{name}");
}
table.Columns.Add(name);
}
for (var rowNum = startRow + 1; rowNum <= ws.Dimension.End.Row; rowNum++)
{
var row = table.NewRow();
var values = new string[table.Columns.Count];
for (var colNum = startCol; colNum <= table.Columns.Count; colNum++)
{
if (colNum <= table.Columns.Count + 1)
values[colNum - 1] = ws.Cells[rowNum, colNum]?.Value?.ToString()?.Trim().RemoveEnter().RemoveLineBreak() ?? "";
}
row.ItemArray = values;
table.Rows.Add(row);
}
return table;
}
catch (Exception ex)
{
Log.Error($"读取Excel出现错误: {ex.Message}");
throw;
}
}
#endregion
#region Export Excel
/// <summary>
/// 导出Excel
/// </summary>
/// <param name="filepath"></param>
/// <param name="contents"></param>
/// <returns></returns>
public static bool Export(string filepath, params ExcelExportOption[] contents)
{
return Export(contents.ToList(), filepath);
}
/// <summary>
/// 导出Excel
/// </summary>
/// <param name="data"></param>
/// <param name="filepath">路径</param>
/// <returns></returns>
public static bool Export(List<ExcelExportOption> data, string filepath)
{
try
{
if (File.Exists(filepath))
File.Delete(filepath);
using (Stream newStream = new FileStream(filepath, FileMode.Create, FileAccess.ReadWrite)) // 注意 FileAccess 参数
{
using (ExcelPackage package = new ExcelPackage(newStream))
{
foreach (var item in data)
{
if (package.Workbook.Worksheets.Any(t => t.Name == item.Name))
package.Workbook.Worksheets.Delete(item.Name);
var worksheet = package.Workbook.Worksheets.Add(item.Name);
CreateWorksheet(worksheet, item);
}
package.Save();
return true;
}
}
}
catch (Exception ex)
{
Log.Error("导出Excel异常");
}
return false;
}
/// <summary>
/// 导出Excel
/// </summary>
/// <param name="worksheet"></param>
/// <param name="exportOptions"></param>
public static void CreateWorksheet(ExcelWorksheet worksheet, ExcelExportOption exportOptions)
{
exportOptions.Rows = exportOptions.Rows ?? new List<Dictionary<string, object>> { };
//获取列头最大行
List<int> all = new List<int>();
GetTreeCount(exportOptions.Columns, all);
int headRow = all.Max();
//获取列头
var headList = GetHeads(exportOptions.Columns.OrderBy(t => t.Sort).ToList(), exportOptions.IgnoreColumns);
//列数行数
int InceptionRow = 1; int InceptionRol = 1;
// 判断是否有Title
if (!string.IsNullOrEmpty(exportOptions.Title))
{
//生成标题
int titleColSpan = headList.Count;
worksheet.Cells[1, 1, 1, titleColSpan].Merge = true;
worksheet.Cells[1, 1, 1, titleColSpan].Value = exportOptions.Title;
worksheet.Cells[1, 1, 1, titleColSpan].Style.Font.Size = 16;
worksheet.Cells[1, 1, 1, titleColSpan].Style.Font.Bold = true;
worksheet.Cells[1, 1, 1, titleColSpan].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
worksheet.Cells[1, 1, 1, titleColSpan].Style.VerticalAlignment = ExcelVerticalAlignment.Center;
worksheet.Cells[1, 1, 1, titleColSpan].Style.Border.BorderAround(ExcelBorderStyle.Thin);
//行高
worksheet.Row(1).Height = 30;
// 调整headRow
headRow++;
InceptionRow = 2;
}
//生成列头
GenerateHeads(worksheet, exportOptions.Columns, exportOptions.IgnoreColumns, headRow, InceptionRow, InceptionRol);
for (int col = 0; col < headList.Count; col++)
{
for (int row = 0; row < exportOptions.Rows.Count; row++)
{
var temp = exportOptions.Rows[row];
// 缩进
if (col == 0 && temp.ContainsKey(ExcelExportCommon.缩进) && int.TryParse(temp[ExcelExportCommon.缩进]?.ToString() ?? "0", out int indent))
{
worksheet.Cells[row + headRow + 1, col + 1].Style.Indent = indent * 2;
}
if (temp.TryGetValue(headList[col].Field, out object? value))
{
// 如果是日期类型,设置日期格式
if (value is DateTime tempTime)
{
value = tempTime.ToString();
worksheet.Cells[row + headRow + 1, col + 1].Value = value;
worksheet.Cells[row + headRow + 1, col + 1].Style.Numberformat.Format = "yyyy年mm月dd日";
}
// 否则将值写入单元格,如果值为 null,则写入空字符串
else
{
worksheet.Cells[row + headRow + 1, col + 1].Value = value ?? "";
}
// link跳转
if (temp.TryGetValue(ExcelExportCommon.链接, out object? hyperLink))
{
worksheet.Cells[row + headRow + 1, col + 1].Hyperlink = new ExcelHyperLink($"'{hyperLink}'!A1", value?.ToString() ?? "链接");
worksheet.Cells[row + headRow + 1, col + 1].Style.Font.Color.SetColor(Color.Blue);
}
}
}
}
if (exportOptions.Aggregate)
{
var sRow = headRow + 1;
var eRow = exportOptions.Rows.Count + headRow;
worksheet.SetValue(eRow + 1, 1, "合计");
for (int col = 2; col <= headList.Count; col++)
{
var sum = $"SUM({new ExcelAddress(sRow, col, eRow, col).Address})";
worksheet.Cells[eRow + 1, col].Formula = $"IF({sum}=0, \"\", {sum})";
}
}
#region 样式设置
for (int row = worksheet.Dimension.Start.Row; row <= worksheet.Dimension.End.Row; row++)
{
if (!string.IsNullOrEmpty(exportOptions.Title) && row == 1) continue;
worksheet.Row(row).Height = 20;
for (int col = worksheet.Dimension.Start.Column; col <= worksheet.Dimension.End.Column; col++)
{
var horizontalAlignment = ExcelHorizontalAlignment.Center;
if (col - 1 >= 0 && col <= headList.Count)
{
horizontalAlignment = (headList.ElementAt(col - 1).Alignment?.ToUpper()) switch
{
"LEFT" => ExcelHorizontalAlignment.Left,
"RIGHT" => ExcelHorizontalAlignment.Right,
"CENTER" => ExcelHorizontalAlignment.Center,
_ => ExcelHorizontalAlignment.Center,
};
}
worksheet.Cells[row, col].Style.HorizontalAlignment = horizontalAlignment;
worksheet.Cells[row, col].Style.VerticalAlignment = ExcelVerticalAlignment.Center;
worksheet.Cells[row, col].Style.Border.BorderAround(ExcelBorderStyle.Thin);
}
}
worksheet.View.FreezePanes(headRow + 1, 1);
worksheet.Cells.AutoFitColumns();
for (int col = worksheet.Dimension.Start.Column; col <= worksheet.Dimension.End.Column; col++)
{
var width = 10d;
if (col - 1 >= 0 && col <= headList.Count)
width = Enumerable.ElementAt(headList, col - 1)?.Width ?? width;
worksheet.Column(col).Width = width;
}
#endregion
}
/// <summary>
/// 获得列头
/// </summary>
/// <param name="columns"></param>
/// <param name="ignoreColumns"></param>
/// <returns></returns>
private static List<ExcelColumn> GetHeads(List<ExcelColumn> columns, List<string> ignoreColumns)
{
List<ExcelColumn> heads = new List<ExcelColumn>();
foreach (var item in columns.OrderBy(w => w.Sort))
{
if (!ignoreColumns.Contains(item.Field) && !ignoreColumns.Contains(item.Title))
{
if (item.Children?.Any() != true)
heads.Add(item);
else
heads.AddRange(GetHeads(item.Children, ignoreColumns));
}
}
return heads;
}
/// <summary>
/// 生成excel列头
/// </summary>
/// <param name="worksheet"></param>
/// <param name="columns"></param>
/// <param name="ignoreColumns"></param>
/// <param name="headRow"></param>
/// <param name="row"></param>
/// <param name="col"></param>
private static void GenerateHeads(ExcelWorksheet worksheet, List<ExcelColumn> columns, List<string> ignoreColumns, int headRow, int row, int col)
{
int colIndex = col;
foreach (var item in columns.OrderBy(w => w.Sort))
{
if (!ignoreColumns.Contains(item.Title) && !ignoreColumns.Contains(item.Field))
{
int children = GetMinChildCount(item.Children, 0);
worksheet.Cells[row, colIndex].Value = string.IsNullOrEmpty(item.Title) ? item.Field : item.Title;
if (!string.IsNullOrWhiteSpace(item.Comment))
worksheet.Cells[row, colIndex].AddComment(item.Comment, "");
worksheet.Cells[row, colIndex].Style.Font.Bold = true;
if (children != 0)
{
worksheet.Cells[row, colIndex, row, colIndex + children - 1].Merge = true;
GenerateHeads(worksheet, item.Children, ignoreColumns, headRow, row + 1, colIndex);
colIndex += children;
}
else
{
worksheet.Cells[row, colIndex, headRow, colIndex].Merge = true;
colIndex++;
}
}
}
}
/// <summary>
/// 获取树最大深度
/// </summary>
/// <param name="columns"></param>
/// <param name="all"></param>
/// <param name="level"></param>
private static void GetTreeCount(List<ExcelColumn> columns, List<int> all, int level = 1)
{
foreach (var item in columns.Select(w => w.Children))
{
if (item?.Any() == true)
{
GetTreeCount(item, all, level + 1);
}
else
all.Add(level);
}
}
/// <summary>
/// 获得最小的子集数量
/// </summary>
/// <param name="columns"></param>
/// <param name="count"></param>
/// <returns></returns>
private static int GetMinChildCount(List<ExcelColumn> columns, int count)
{
if (columns?.Any() == true)
{
foreach (var col in columns.Select(w => w.Children))
{
if (col?.Any() != true)
count++;
else
count = GetMinChildCount(col, count);
}
}
return count;
}
#endregion
}
/// <summary>
/// 常量
/// </summary>
public class ExcelExportCommon
{
/// 缩进
public const string 缩进 = "@Indent";
/// 链接
public const string 链接 = "@Hyperlink";
/// ctor
protected ExcelExportCommon() { }
}
/// <summary>
/// 导出Excel配置
/// </summary>
public class ExcelExportOption
{
/// ctor
public ExcelExportOption()
{
Rows = new List<Dictionary<string, object>>();
Columns = new List<ExcelColumn>();
IgnoreColumns = new List<string>();
}
/// <summary>
/// 标题
/// </summary>
public string? Title { get; set; }
/// <summary>
/// 工作表名
/// </summary>
public string? Name { get; set; }
/// <summary>
/// 数据
/// </summary>
public List<Dictionary<string, object>> Rows { get; set; }
/// <summary>
/// 列头
/// </summary>
public List<ExcelColumn> Columns { get; set; }
/// <summary>
/// 不需要导出的列
/// </summary>
public List<string> IgnoreColumns { get; set; }
/// <summary>
/// 添加汇总
/// </summary>
public bool Aggregate { get; set; } = false;
}
/// <summary>
/// 导出Excel列头配置
/// </summary>
public class ExcelColumn
{
/// <inheritdoc/>
public ExcelColumn()
{
}
/// ctor
public ExcelColumn(string title, string field, double width = 20, string alignment = "Center", decimal sort = 0m, List<ExcelColumn>? children = null, string comment = "")
{
Title = title;
Field = field;
Width = width;
Alignment = alignment;
Sort = sort;
Comment = comment;
Children = children ?? new List<ExcelColumn>();
}
/// <summary>
/// 显示名称
/// </summary>
public string Title { get; set; }
/// <summary>
/// 字段名称
/// </summary>
public string Field { get; set; }
/// <summary>
/// 列宽
/// </summary>
public double? Width { get; set; }
/// <summary>
/// Left,Center,Right,
/// </summary>
public string? Alignment { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Comment { get; set; }
/// <summary>
/// 排序
/// </summary>
public decimal Sort { get; set; }
/// <summary>
/// 子列头
/// </summary>
public List<ExcelColumn> Children { get; set; }
}
}
\ No newline at end of file
using System;
using System.IO;
namespace Performance.Infrastructure
{
/// <summary>
/// 系统路径
/// </summary>
public class SystemPath
{
/// ctor
public SystemPath()
{
var paths = new string[] { Temp, Download, Upload, Db, Backup };
foreach (var item in paths)
{
if (!Directory.Exists(item)) Directory.CreateDirectory(item);
}
}
/// <summary>
/// 软件产出文件
/// </summary>
public static string _files { get; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "files");
/// <summary>
/// 临时文件存放路径
/// </summary>
public string BaseFile => _files;
/// <summary>
/// 临时文件存放路径
/// </summary>
public string Temp { get; } = Path.Combine(_files, "temp-files");
/// <summary>
/// 下载文件存放
/// </summary>
public string Download { get; } = Path.Combine(_files, "download");
/// <summary>
/// 上传文件存放
/// </summary>
public string Upload { get; } = Path.Combine(_files, "upload");
/// <summary>
/// db
/// </summary>
public string Db { get; } = Path.Combine(_files, "db");
/// <summary>
/// 重要文件存档
/// </summary>
public string Backup { get; } = Path.Combine(_files, "backup");
/// <summary>
/// 获取相对路径(文件磁盘路径)
/// </summary>
/// <param name="rootPath"></param>
/// <param name="filePath"></param>
/// <returns></returns>
public string GetRelativePath(string rootPath, string filePath) => GetRelativeUri(rootPath, filePath).Replace('/', Path.DirectorySeparatorChar);
/// <summary>
/// 获取相对路径(URI路径)
/// </summary>
/// <param name="rootPath"></param>
/// <param name="filePath"></param>
/// <returns></returns>
public string GetRelativeUri(string rootPath, string filePath) => Uri.UnescapeDataString(new Uri(rootPath).MakeRelativeUri(new Uri(filePath)).ToString());
}
public static partial class Tools
{
private static readonly Lazy<SystemPath> _lazySystemPath = new Lazy<SystemPath>(() => new SystemPath());
/// 系统路径
public static SystemPath Path { get { return _lazySystemPath.Value; } }
}
}
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace Performance.Infrastructure
{
public static partial class Tools
{
/// <summary>
/// 序列化全局配置(Newtonsoft.Json)
/// </summary>
/// <returns></returns>
public static JsonSerializerSettings GetJsonSerializerSettings(Formatting formatting = Formatting.Indented)
{
var options = new JsonSerializerSettings();
GetJsonSerializerSettings(options);
options.Formatting = formatting;
return options;
}
/// <summary>
/// 序列化全局配置(Newtonsoft.Json)
/// </summary>
/// <returns></returns>
public static void GetJsonSerializerSettings(JsonSerializerSettings options)
{
options.Converters.Add(new IsoDateTimeConverterContent() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
options.Formatting = Formatting.Indented;
options.NullValueHandling = NullValueHandling.Include;
options.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
options.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
options.Culture = new CultureInfo("zh-CN");
options.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
options.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
/// <summary>
/// 数据表转键值对集合
/// </summary>
/// <param name="dynamics">动态类型数据</param>
/// <returns>哈希表数组</returns>
public static List<Dictionary<string, object>> MapDictionary(this List<dynamic> dynamics)
{
return dynamics.Select(expandoDict => new Dictionary<string, object>(expandoDict)).ToList();
}
}
}
......@@ -4,6 +4,7 @@
using System.Linq.Expressions;
using System.Threading.Tasks;
using Dapper;
using Masuit.Tools.Models;
using Microsoft.EntityFrameworkCore;
using Z.EntityFramework.Extensions;
......@@ -89,7 +90,6 @@ public bool RemoveRange(params TEntity[] entities)
context.Set<TEntity>().RemoveRange(entities);
return context.SaveChanges() > 0;
}
public bool RemoveRange(Expression<Func<TEntity, bool>> exp)
{
var query = context.Set<TEntity>().AsQueryable().Where(exp);
......@@ -145,9 +145,9 @@ public List<TEntity> GetEntities(Expression<Func<TEntity, bool>> exp)
return context.Set<TEntity>().AsQueryable().Where(exp).ToList();
}
public List<TEntity> GetEntitiesForPaging(int Page, int pageSize, Expression<Func<TEntity, bool>> exp)
public PagedList<TEntity> GetEntitiesForPaging(int Page, int pageSize, Expression<Func<TEntity, bool>> exp)
{
return context.Set<TEntity>().AsQueryable().Where(exp).Skip((Page - 1) * pageSize).Take(pageSize).ToList();
return context.Set<TEntity>().AsQueryable().Where(exp).Skip((Page - 1) * pageSize).Take(pageSize).ToPagedList(Page, pageSize);
}
public TEntity GetEntity(Expression<Func<TEntity, bool>> exp)
......@@ -155,6 +155,10 @@ public TEntity GetEntity(Expression<Func<TEntity, bool>> exp)
return context.Set<TEntity>().AsQueryable().FirstOrDefault(exp);
}
public async Task<TEntity> GetEntityAsync(Expression<Func<TEntity, bool>> exp)
{
return await context.Set<TEntity>().FirstOrDefaultAsync(exp);
}
#region Bulk
public void BulkInsert(IEnumerable<TEntity> entities)
......
using Performance.EntityModels;
namespace Performance.Repository
{
/// <summary>
/// low_proc Repository
/// </summary>
public partial class PerforLowProcRepository : PerforRepository<low_proc>
{
public PerforLowProcRepository(PerformanceDbContext context) : base(context)
{
}
}
}
using AutoMapper;
using Dapper;
using Masuit.Tools;
using Masuit.Tools.Models;
using Microsoft.Extensions.Options;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using Performance.DtoModels;
using Performance.DtoModels.AppSettings;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Infrastructure.Models;
using Performance.Repository;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Security.Claims;
using System.Threading.Tasks;
using Yitter.IdGenerator;
using static Performance.DtoModels.ManagementDept;
namespace Performance.Services
{
/// <summary>
/// 可配置数据查询
/// </summary>
public class LowProcService : IAutoInjection
{
private readonly PerforLowProcRepository _lowProcRepository;
private readonly IMapper _mapper;
private readonly IOptions<AppConnection> _options;
private readonly int _commandTimeout = 60 * 5;
/// ctor
public LowProcService(PerforLowProcRepository lowProcRepository, IMapper mapper, IOptions<AppConnection> options)
{
_lowProcRepository = lowProcRepository;
_mapper = mapper;
_options = options;
}
/// <summary>
/// 扩展查询
/// </summary>
/// <param name="title">扩展查询名</param>
/// <param name="page"></param>
/// <param name="size"></param>
/// <returns></returns>
public PagedList<low_proc> GetListAsync(string? title, int page, int size)
{
Expression<Func<low_proc, bool>> predicate = w => true;
predicate = predicate
.AndIf(!string.IsNullOrWhiteSpace(title), w => w.Title.Contains(title!));
var result = _lowProcRepository.GetEntitiesForPaging(page, size, predicate);
return result;
}
/// <summary>
/// 查询配置信息
/// </summary>
/// <param name="procId"></param>
/// <returns></returns>
public async Task<low_proc?> GetAsync(long procId) => await _lowProcRepository.GetEntityAsync(x => x.ProcId == procId);
/// <summary>
/// 新增扩展查询记录
/// </summary>
/// <param name="procDto"></param>
/// <returns></returns>
/// <exception cref="DomainException"></exception>
public async Task AddAsync(LowProcRequest procDto, int userid)
{
if (string.IsNullOrEmpty(procDto?.Script))
throw new PerformanceException("您提交的扩展查询为空,请填写后重试");
var low_Proc = await _lowProcRepository.GetEntityAsync(w => w.Title == procDto.Title);
if (low_Proc != null)
throw new PerformanceException("您提交的扩展查询名已存在,请修改后重试");
var proc = _mapper.Map<low_proc>(procDto);
proc.ProcId = YitIdHelper.NextId();
proc.CreateBy = userid;
proc.CreateTime = DateTime.Now;
proc.UpdateBy = userid;
proc.UpdateTime = DateTime.Now;
await _lowProcRepository.AddAsync(proc);
}
/// <summary>
/// 修改扩展查询记录
/// </summary>
/// <param name="procId"></param>
/// <param name="procDto"></param>
/// <returns></returns>
/// <exception cref="DomainException"></exception>
public async Task UpdateAsync(long procId, int userid, LowProcRequest procDto)
{
if (string.IsNullOrEmpty(procDto?.Script))
throw new PerformanceException("您提交的扩展查询为空,请填写后重试");
var proc = await _lowProcRepository.GetEntityAsync(w => w.ProcId == procId)
?? throw new PerformanceException("未找到需要修改的扩展查询,请检查后重试");
_mapper.Map(procDto, proc);
proc.UpdateBy = userid;
proc.UpdateTime = DateTime.Now;
_lowProcRepository.Update(proc);
}
/// <summary>
/// 删除扩展查询记录
/// </summary>
/// <param name="procIds"></param>
/// <returns></returns>
/// <exception cref="DomainException"></exception>
public void DeleteAsync(params long[] procIds)
{
if (procIds.Length == 0)
throw new PerformanceException("您提交的删除信息无效,请检查后重试!");
var del = _lowProcRepository.GetEntities(w => procIds.Contains(w.ProcId));
_lowProcRepository.RemoveRange(del.ToArray());
}
/// <summary>
/// 扩展数据
/// </summary>
/// <param name="procId"></param>
/// <param name="queries"></param>
/// <param name="page"></param>
/// <param name="size"></param>
public async Task<PagedList<dynamic, ColumnResponse, object>> GetDatumAsync(long procId, List<DynamicQuery> queries, int page, int size, Dictionary<string, object> args)
{
var proc = await _lowProcRepository.GetEntityAsync(x => x.ProcId == procId)
?? throw new PerformanceException("当前查询数据信息错误,请检查配置信息");
foreach (var query in queries)
{
if (query.Field.Equals("allotId", StringComparison.OrdinalIgnoreCase))
{
if (long.TryParse(query.Value, out long allotIdValue))
args.AddOrUpdate(query.Field, allotIdValue, allotIdValue);
else
args.AddOrUpdate(query.Field, 0L, 0L);
}
else
{
args.AddOrUpdate(query.Field, query.Value ?? string.Empty, query.Value ?? string.Empty);
}
}
if (string.IsNullOrWhiteSpace(proc.Script))
throw new PerformanceException("当前查询尚未配置脚本,请配置后重试");
(IQueryable<dynamic> data, List<ColumnResponse> columns) = await GetExtensionDatumAsync(proc.Script, args);
var total = new Dictionary<string, object?>();
if (data.Any())
{
var dict = (IDictionary<string, object>)data.First();
var keys = dict.Select(w => w.Key).ToList();
foreach (var key in keys)
{
var col = columns.FirstOrDefault(w => w.Field.Equals(key, StringComparison.OrdinalIgnoreCase));
if (col != null)
col.Field = key;
}
foreach (var item in queries.Where(w => !string.IsNullOrEmpty(w.Value)))
{
var field = keys.FirstOrDefault(col => col.Equals(item.Field, StringComparison.OrdinalIgnoreCase));
if (!string.IsNullOrEmpty(field))
{
var exp = $"{field} != null && {field}.ToString().Contains(@0, StringComparison.OrdinalIgnoreCase)";
data = data.Where(exp, item.Value);
}
}
foreach (var item in columns)
{
object? sumValue = null;
if (item.Formatter == Formatter.numeric.ToString())
{
var field = keys.FirstOrDefault(col => col.Equals(item.Field, StringComparison.OrdinalIgnoreCase));
if (!string.IsNullOrEmpty(field))
sumValue = data.Select(field).ToDynamicList().Cast<decimal?>().Sum();
}
total.AddOrUpdate(item.Field, sumValue, sumValue);
}
}
page = data.Count() <= size ? 1 : page;
var paged = data.ToPagedList(page, size);
return new PagedList<dynamic, ColumnResponse, object>(paged, columns, new List<object> { total });
}
/// <summary>
/// 自识别存储过程查询
/// </summary>
/// <param name="script"></param>
/// <param name="args"></param>
/// <returns></returns>
public async Task<(IQueryable<dynamic> data, List<ColumnResponse> columns)> GetExtensionDatumAsync(string script, Dictionary<string, object> args)
{
using (var conn = new MySqlConnection(_options.Value.PerformanceConnectionString))
{
if (conn.State != ConnectionState.Open) conn.Open();
var multi = await conn.QueryMultipleAsync(script, args, commandTimeout: _commandTimeout);
var data = (await multi.ReadAsync()).AsQueryable();
var columns = (await multi.ReadAsync<ColumnResponse>()).AsList();
columns.ForEach(column =>
{
column.Visible ??= true;
column.Sort = columns.Max(w => w.Sort ?? 1) + 1;
});
columns = columns.OrderBy(w => w.Sort).ToList();
return (data, columns);
}
}
}
}
......@@ -15,6 +15,8 @@
<PackageReference Include="GraphQL" Version="2.4.0" />
<PackageReference Include="MassTransit.AspNetCore" Version="7.2.4" />
<PackageReference Include="Polly" Version="7.2.2" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.4.5" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
</ItemGroup>
<ItemGroup>
......
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