Files
SecMPS/api_sqlsugar/VolPro.Core/Print/PrintContainer.cs
2026-05-15 23:22:48 +08:00

437 lines
18 KiB
C#

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using VolPro.Core.DBManager;
using VolPro.Core.DbSqlSugar;
using VolPro.Core.Extensions;
using VolPro.Core.Infrastructure;
using VolPro.Core.ManageUser;
using VolPro.Core.WorkFlow;
using VolPro.Entity.DomainModels;
namespace VolPro.Core.Print
{
public class PrintContainer
{
public static List<PrintOptions> _print = new List<PrintOptions>();
private static PrintContainer _instance;
public static PrintContainer Instance
{
get
{
if (_instance != null)
{
return _instance;
}
_instance = new PrintContainer();
return _instance;
}
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="name">打印分类的名称</param>
/// <param name="printFields">可以打印的字段</param>
/// <param name=""></param>
/// <returns></returns>
public PrintContainer Use<T>(string name, [NotNull] Expression<Func<T, object>> printFields, List<CustomField> customFields = null)
{
if (_print.Any(x => x.TableType == typeof(T)))
{
return Instance;
}
Type type = typeof(T);
_print.Add(new PrintOptions()
{
TableType = type,
Name = name ?? type.GetEntityTableCnName(),
TableName = type.Name,
Fields = printFields.GetExpressionProperty(),
CustomFields = customFields
});
return Instance;
}
public PrintContainer Use<T, Detail>(
string name,
[NotNull] Expression<Func<T, object>> printFields,
List<CustomField> customFields,
string detailName,
[NotNull] Expression<Func<Detail, object>> detailPrintFields,
List<CustomField> detailCustomFields = null) where Detail : class
{
return Use(name, printFields, customFields, detail: new PrintDetailOptions<Detail>()
{
Name = detailName,
PrintFields = detailPrintFields,
CustomFields = detailCustomFields
});
}
/// <summary>
///
/// </summary>
/// <typeparam name="T">打印的主表</typeparam>
/// <typeparam name="Detail">打印的明细表</typeparam>
/// <param name="name">打印分类的名称</param>
/// <param name="printFields">可以打印的字段</param>
/// <param name="detailName">打印的明细表名称</param>
/// <param name="printFields">可以打印的明细表字段</param>
/// <param name=""></param>
/// <returns></returns>
public PrintContainer Use<T, Detail>(string name,
[NotNull] Expression<Func<T, object>> printFields,
string detailName,
[NotNull] Expression<Func<Detail, object>> detailPrintFields
) where Detail : class
{
return Instance.Use(name, printFields, null, detailName, detailPrintFields);
}
public PrintContainer Use<T, Detail>(string name,
[NotNull] Expression<Func<T, object>> printFields,
List<CustomField> customFields,
[NotNull] PrintDetailOptions<Detail> detail
) where Detail : class
{
return Instance.Use<T, Detail, Detail>(name, printFields, customFields, detail, null);
}
public PrintContainer Use<T, Detail1, Detail2>(string name,
[NotNull] Expression<Func<T, object>> printFields,
List<CustomField> customFields,
[NotNull] PrintDetailOptions<Detail1> detail1,
PrintDetailOptions<Detail2> detail2
) where Detail1 : class where Detail2 : class
{
return Instance.Use<T, Detail1, Detail2, Detail2>(name, printFields, customFields, detail1, detail2, null);
}
public PrintContainer Use<T, Detail1, Detail2, Detail3>(string name,
[NotNull] Expression<Func<T, object>> printFields,
List<CustomField> customFields,
[NotNull] PrintDetailOptions<Detail1> detail1,
PrintDetailOptions<Detail2> detail2,
PrintDetailOptions<Detail3> detail3
) where Detail1 : class where Detail2 : class where Detail3 : class
{
if (_print.Any(x => x.TableType == typeof(T)))
{
return Instance;
}
Type type = typeof(T);
var PrintDetails = new List<PrintDetail>();
if (detail1 != null)
{
PrintDetails.Add(GetPrintDetail(detail1));
}
if (detail2 != null)
{
PrintDetails.Add(GetPrintDetail(detail2));
}
if (detail3 != null)
{
PrintDetails.Add(GetPrintDetail(detail3));
}
_print.Add(new PrintOptions()
{
TableType = type,
Name = name ?? type.GetEntityTableCnName(),
TableName = type.Name,
Fields = printFields.GetExpressionProperty(),
CustomFields = customFields,
PrintDetails = PrintDetails
});
return Instance;
}
private PrintDetail GetPrintDetail<T>(PrintDetailOptions<T> detail) where T : class
{
return new PrintDetail()
{
DetailTableType = typeof(T),
DetailName = detail.Name ?? typeof(T).GetEntityTableCnName(),
DetailTableName = typeof(T).Name,
DetailFields = detail.PrintFields.GetExpressionProperty(),
CustomgFields = detail.CustomFields
};
}
/// <summary>
/// 获取下拉框数据源
/// </summary>
/// <returns></returns>
public static object GetSelect()
{
//只显示有权限的表
var permissions = UserContext.Current.Permissions;
return _print
.Where(x => permissions.Any(c => c.TableName == x.TableName.ToLower()))
.Select(s => new { key = s.TableName, value = s.Name }).ToList();
}
/// <summary>
/// 获取下拉框数据源
/// </summary>
/// <returns></returns>
public static object GetOptions(string table)
{
//只显示有权限的表
var permissions = UserContext.Current.Permissions;
var query = _print
.Where(x => permissions.Any(c => c.TableName == x.TableName.ToLower()));
if (!string.IsNullOrEmpty(table))
{
query = query.Where(x => x.TableName == table);
}
// .GroupBy(c=>new { c.TableName})
var data = query.Select(s => new
{
s.TableName,
s.Name,
Fields = s.Fields.Select(x => x).ToList(),//.Union((s.CustomFields?.Select(s=>s.Field)??new List<string>()).ToList()).ToList(),
details = (s.PrintDetails ?? new List<PrintDetail>())
//.Select(c=>c.DetailFields)
//s.DetailName,
//s.DetailTableName,
//DetailFields = (s.DetailFields ?? new string[] { }).Select(x => x).ToList().Union((s.DetailCustomgFields?.Select(s => s.Field) ?? new List<string>()).ToList()).ToList(),
}).ToList();
var tables = data.Select(s => s.TableName).ToList();
//明细表配置
var detailTableNames = data.SelectMany(x => x.details.Select(c => c.DetailTableName)).Where(x => x != null);
tables.AddRange(detailTableNames);
var tableOptions = DBServerProvider.DbContext.Set<Sys_TableColumn>().Where(x => tables.Contains(x.TableName))
.OrderByDescending(x => x.OrderNo)
.Select(s => new { s.TableName, name = s.ColumnCnName, width = s.ColumnWidth, field = s.ColumnName, s.EditType, s.DropNo, TableType = s.IsImage })
.ToList();
var options = data.Select(s => new
{
s.TableName,
s.Name,
Fields = tableOptions.Where(c => c.TableName == s.TableName && s.Fields.Contains(c.field)).ToList(),
//明细表
TemplateDetails = s.details.Select(c => new
{
c.DetailName,
c.DetailTableName,
DetailFields = tableOptions.Where(x => x.TableName == c.DetailTableName && c.DetailFields.Contains(x.field))
.Select(s => new { s.field, s.name, TableType = s.TableType ?? -1 }).ToList()
.Union((c.CustomgFields ?? new List<CustomField>()).Select(s => new { field = s.Field, name = s.Name, TableType = -1 }))
})
}).ToList();
return options;
}
public static async Task<object> GetPrintDataAsync(PrintQuery query)
{
var ops = _print.Where(x => x.TableName == query.Table).FirstOrDefault();
//if ((query.Detail || query.BatchMainAndDetail) && ops.DetailTableType == null)
//{
// throw new Exception($"startup里面必须配置[{ops.TableName}]的明细表");
//}
query.TemplateName = await DBServerProvider.DbContext.Set<Sys_PrintOptions>()
.Where(x => x.PrintOptionsId == query.TemplateId)
.Select(ops => ops.CustomName).FirstOrDefaultAsync();
var list = typeof(PrintContainer).GetMethod("GetDataAsync")
.MakeGenericMethod(new Type[] { ops.TableType })
.Invoke(null, new object[] { query.Ids, query.Table, ops.Fields.Select(x => x).ToList(), ops.PrintDetails, query, ops }) as Task<object>;
return await list;
}
/// <summary>
/// 获取明细表配置
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="ids"></param>
/// <param name="table"></param>
/// <param name="fields"></param>
/// <param name="printDetails"></param>
/// <param name="parms"></param>
/// <param name="ops"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static async Task<object> GetDataAsync<T>(object[] ids, string table, List<string> fields, List<PrintDetail> printDetails, PrintQuery parms, PrintOptions ops)
where T : class,new() //where Detail : class
{
if (ids == null || ids.Length == 0)
{
return new List<Dictionary<string, object>>();
}
string key = typeof(T).GetKeyName();
if (parms.Detail || (printDetails?.Count > 0))
{
fields.Add(key);
}
//else if (parms.BatchMainAndDetail || parms.BatchMain)
//{
//}
//else
//{
// //不是批量打印的,默认只查第一条
// ids = new object[] { ids[0] };
//}
PrintFilter filter = new PrintCustom();
var express = key.CreateExpression<T>(ids, Enums.LinqExpressionType.In);
var dbContext = DBServerProvider.GetEntityDbContext<T>();
var queryable = dbContext.Set<T>().Where(express);
queryable = filter.Query(queryable, parms);
var entities = await queryable.ToListAsync();
//主表数据
List<Dictionary<string, object>> list = await ConvertListAsync(entities, ids, table, fields, parms);
if (printDetails == null)
{
printDetails = new List<PrintDetail>();
}
foreach (var mainData in list)
{
//获取明细表
foreach (var detail in printDetails)
{
var pro = detail.DetailTableType.GetProperty(key);
if (pro == null)
{
throw new Exception($"明细表必须包括主表字段[{key}]");
}
//var detailExpress = key.CreateExpression<Detail>(ids, Enums.LinqExpressionType.In);
//var detailQueryable = DBServerProvider.GetEFDbContext<Detail>().Set<Detail>().Where(detailExpress);
//detailQueryable = filter.QueryDetail(detailQueryable, parms);
//var detailEntities = await detailQueryable.ToListAsync();
fields = detail.DetailFields.ToList();
fields.Add(key);
//var detailList = await ConvertListAsync(detailEntities, ids, detail.DetailTableName, fields, parms);
var obj = typeof(PrintContainer).GetMethod("GetDetailDataAsync")
.MakeGenericMethod(new Type[] { detail.DetailTableType })
.Invoke(null, new object[] { key, ids, fields, parms });
var detailList = await (obj as Task<List<Dictionary<string, object>>>);
string keyValue = mainData[key].ToString();
List<Dictionary<string, object>> detailDic = new List<Dictionary<string, object>>(); ;
foreach (var detailItem in detailList)
{
if (detailItem[key].ToString() == keyValue)
{
detailDic.Add(detailItem);
}
}
mainData[detail.DetailTableName] = detailDic;
}
}
list = filter.QueryResult<T>(list, parms, dbContext);
return list;
}
public static async Task<List<Dictionary<string, object>>> GetDetailDataAsync<Detail>(string key, object[] ids, List<string> fields, PrintQuery parms)
where Detail : class, new()
{
PrintFilter filter = new PrintCustom();
var detailExpress = key.CreateExpression<Detail>(ids, Enums.LinqExpressionType.In);
var detailQueryable = DBServerProvider.GetEntityDbContext<Detail>().Set<Detail>(true).Where(detailExpress);
detailQueryable = filter.QueryDetail(detailQueryable, parms);
var detailEntities = await detailQueryable.ToListAsync();
var data = await ConvertListAsync(detailEntities, ids, typeof(Detail).Name, fields, parms);
return data;
}
private static async Task<List<Dictionary<string, object>>> ConvertListAsync<T>(List<T> entities, object[] ids, string table, List<string> fields, PrintQuery query)
{
var columns = await DBServerProvider.DbContext.Set<Sys_TableColumn>().Where(c => c.TableName == table).ToListAsync();
var tableOptions = columns.Where(c => fields.Contains(c.ColumnName)).
Select(s => new { s.ColumnName, s.ColumnCnName, s.DropNo, s.ColumnType, isDate = s.IsImage == 4 || s.EditType == "date" });
List<Sys_Dictionary> dictionaries = new List<Sys_Dictionary>();
var dicNos = tableOptions.Select(s => s.DropNo).ToList();
if (dicNos.Count > 0)
{
dictionaries = DictionaryManager.GetDictionaries(dicNos, true).ToList();
}
List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
var properties = typeof(T).GetProperties();
foreach (var data in entities)
{
Dictionary<string, object> item = new Dictionary<string, object>();
foreach (var field in fields)
{
var property = properties.Where(c => c.Name == field).FirstOrDefault();
var option = tableOptions.Where(c => c.ColumnName == field).FirstOrDefault();
string value = null;
if (option.ColumnType == "decimal")
{
var deciVal = property.GetValue(data);
if (deciVal != null)
{
value = ((decimal)deciVal).ToString("G29");
}
}
else
{
value = property.GetValue(data)?.ToString();
}
string name = option?.ColumnCnName;
if (string.IsNullOrEmpty(name))
{
name = property.GetDisplayName();
}
if (option == null || string.IsNullOrEmpty(value))
{
item[property.Name] = value = value ?? "";
continue;
}
if (option.isDate)
{
value = value.GetDateTime().Value.ToString("yyyy-MM-dd");
}
else if (!string.IsNullOrEmpty(option.DropNo))
{
string val = dictionaries.Where(c => c.DicNo == option.DropNo).FirstOrDefault()
?.Sys_DictionaryList
//这里多选的暂时没处理
?.Where(c => c.DicValue == value)?.Select(s => s.DicName)
.FirstOrDefault();
if (!string.IsNullOrEmpty(val))
{
value = val;
}
}
item[property.Name] = value;
}
list.Add(item);
}
return list;
}
}
}