This commit is contained in:
2025-07-04 09:50:02 +08:00
commit 3d800dbd11
2564 changed files with 1353015 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyCode.Project.Infrastructure.Imports
{
/// <summary>
/// 默认值属性类
/// </summary>
public class DefaultValueProperty
{
/// <summary>
/// 实体的属性名称
/// </summary>
public string EntityProp { get; set; }
/// <summary>
/// 默认值
/// </summary>
public object DefaultValue { get; set; }
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyCode.Project.Infrastructure.Imports
{
/// <summary>
/// 导入Excel数据任务接口
/// </summary>
public interface IImportExcelProcess
{
/// <summary>
/// 执行导入Excel数据的方法
/// </summary>
ImportResult RunImportExcelProcess();
/// <summary>
/// 获取导入Excel数据的方法
/// </summary>
List<object> GetImportExcelData();
}
/// <summary>
/// 导入数据的处理事件
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="entityList">数据源</param>
public delegate object ImportEvent<T>(List<T> entityList);
/// <summary>
/// 获取导入数据的处理事件
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="entityList">数据源</param>
/// <returns></returns>
public delegate List<T> GetDataEvent<T>(List<T> entityList);
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyCode.Project.Infrastructure.Imports
{
public class ImportAct
{
/// <summary>
/// 导入类型 1:卡券 2:根据手机号码得到会员信息
/// </summary>
public int ImportType { get; set; }
/// <summary>
/// 传参
/// </summary>
public object Param { get; set; }
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyCode.Project.Infrastructure.Imports
{
/// <summary>
/// 实体的子属性
/// </summary>
public class ImportChildProperty
{
/// <summary>
/// 实体的属性名称
/// </summary>
public string EntityProp { get; set; }
/// <summary>
/// 属性的类型
/// </summary>
public Type PropType { get; set; }
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyCode.Project.Infrastructure.Imports
{
/// <summary>
/// 复杂类型数据属性类
/// </summary>
public class ImportComplexProperty:ImportProperty
{
/// <summary>
/// 复杂属性的名称
/// </summary>
public string ComplexPropName { get; set; }
/// <summary>
/// 复杂属性的类型
/// </summary>
public Type ComplexPropType { get; set; }
/// <summary>
/// 子属性类型
/// </summary>
public ImportChildProperty ChildProperty { get; set; }
}
}

View File

@@ -0,0 +1,307 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MyCode.Project.Infrastructure.Common;
using MyCode.Project.Infrastructure.Exceptions;
namespace MyCode.Project.Infrastructure.Imports
{
/// <summary>
/// 导入配置类
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
public class ImportConfig<T> where T : class, new()
{
/// <summary>
/// 导入的数据文件转换为Excel操作实体
/// </summary>
public ExcelUtils ExcelUtil { get; set; }
/// <summary>
/// Excel中的标题和实体属性中的字段map例如标题->Title
/// </summary>
public List<ImportProperty> Properties { get; set; }
/// <summary>
/// 默认的属性列这些列不需要Excel导入而是程序中或者导入逻辑中直接设定
/// </summary>
public List<DefaultValueProperty> DefaultProperties { get; private set; }
/// <summary>
/// 复杂类型的属性列
/// </summary>
public List<ImportComplexProperty> ComplexProperties { get; private set; }
/// <summary>
/// 二维数据的属性列
/// </summary>
public List<ImportSplitProperty> SplitProperties { get; private set; }
/// <summary>
/// 子表数据的属性列
/// </summary>
public List<ImportListProperty> ListProperties { get; private set; }
/// <summary>
/// 初始化一个<see cref="ImportConfig{T}"/>类型的实例
/// </summary>
public ImportConfig()
{
Properties=new List<ImportProperty>();
DefaultProperties=new List<DefaultValueProperty>();
ComplexProperties=new List<ImportComplexProperty>();
SplitProperties=new List<ImportSplitProperty>();
ListProperties=new List<ImportListProperty>();
}
#region ValidFormat(Excel的导入格式是否正确)
/// <summary>
/// 验证Excel的导入格式是否正确
/// </summary>
/// <param name="message">消息</param>
/// <returns></returns>
public bool ValidFormat(ref string message)
{
//获取Excel的第一行数据即标题
var columns = this.ExcelUtil.ExportFirstRowData();
foreach (var item in this.Properties)
{
//检查是否存在对应列
if (columns.All(x => x.Trim() != item.Caption))
{
message = string.Format("Excel中找不到[{0}]列!", item.Caption);
return false;
}
}
foreach (var item in this.ComplexProperties)
{
//检查是否存在对应列
if (columns.All(x => x.Trim() != item.Caption))
{
message = string.Format("Excel中找不到[{0}]列!", item.Caption);
return false;
}
}
foreach (var item in this.SplitProperties)
{
//检查是否存在对应列
if (columns.All(x => x.Trim() != item.Caption))
{
message = string.Format("Excel中找不到[{0}]列!", item.Caption);
return false;
}
}
foreach (var item in this.ListProperties)
{
//检查是否存在对应列
if (columns.All(x => x.Trim() != item.Caption))
{
message = string.Format("Excel中找不到[{0}]列!", item.Caption);
return false;
}
}
return true;
}
#endregion
#region GetListData(Excel数据转换为实体列表)
/// <summary>
/// 将Excel数据转换为实体列表
/// </summary>
/// <param name="sourceData">数据源</param>
/// <returns></returns>
public List<T> GetListData(List<Dictionary<string, object>> sourceData)
{
var type = typeof(T);
List<T> resultData=new List<T>();
foreach (var item in sourceData)
{
T entity=new T();
object listItem = null;// 该对象用于存储子表数据
bool isAddList = false;// 判断是否增加子表数据
foreach (var prop in this.ListProperties)
{
var input = item[prop.Caption];
var keyValue = item[prop.PrimaryKeyCaption].ToString();
//验证格式
string message = "";
if (!prop.ValidateInput(input, ref message))
{
throw new BaseException(message);
}
//获取对应类型的值
var value = prop.GetValue(input);
var matersEntity =
resultData.FirstOrDefault(
p => type.GetProperty(prop.PrimaryKey).GetValue(p).ToString() == keyValue);
IList procList = null;
if (matersEntity != null)
{
procList = type.GetProperty(prop.ComplexPropName).GetValue(matersEntity, null) as IList;
//因为主表数据已经存在,所以这个时候只需要增加子表数据。后面的数据直接跳过
isAddList = true;
}
else
{
procList = type.GetProperty(prop.ComplexPropName).GetValue(entity, null) as IList;
if (procList == null)
{
//创建子表集合对象
var procType = prop.ComplexPropType;
var listType = typeof(List<>).MakeGenericType(procType);
procList = Activator.CreateInstance(listType) as IList;
//赋值
type.GetProperty(prop.ComplexPropName).SetValue(entity,procList,null);
}
}
if (listItem == null)
{
//创建一个目标类型的空实例
listItem = prop.ComplexPropType.Assembly.CreateInstance(prop.ComplexPropType.FullName);
//添加到子表集合中
procList.Add(listItem);
}
if (prop.ChildProperty != null)
{
var childEntity =
prop.ChildProperty.PropType.Assembly.CreateInstance(prop.ChildProperty.PropType.FullName);
prop.ChildProperty.PropType.GetProperty(prop.ChildProperty.EntityProp).SetValue(childEntity,value,null);
prop.ComplexPropType.GetProperty(prop.EntityProp).SetValue(listItem, childEntity, null);
}
else
{
prop.ComplexPropType.GetProperty(prop.EntityProp).SetValue(listItem,value,null);
}
}
if (isAddList)
{
//因为主表数据已经存在,所以这个时候只需要增加子表数据。后面的数据直接跳过
continue;
}
//设置基础值
foreach (var prop in this.Properties)
{
var input = item[prop.Caption];
//验证格式
string message = "";
if (!prop.ValidateInput(input, ref message))
{
throw new BaseException(message);
}
//获取对应类型的值
var value = prop.GetValue(input);
type.GetProperty(prop.EntityProp).SetValue(entity,value,null);
}
//设置默认值
foreach (var prop in this.DefaultProperties)
{
type.GetProperty(prop.EntityProp).SetValue(entity,prop.DefaultValue,null);
}
//设置复杂类型属性
foreach (var prop in this.ComplexProperties)
{
var input = item[prop.Caption];
//验证格式
string message = "";
if (!prop.ValidateInput(input, ref message))
{
throw new BaseException(message);
}
//获取对应类型的值
var value = prop.GetValue(input);
var propEntity = type.GetProperty(prop.ComplexPropName).GetValue(entity);
if (propEntity == null)
{
//创建一个目标类型的空实例
propEntity = prop.ComplexPropType.Assembly.CreateInstance(prop.ComplexPropType.FullName);
if (prop.ChildProperty != null)
{
var childEntity =
prop.ChildProperty.PropType.Assembly.CreateInstance(prop.ChildProperty.PropType.FullName);
prop.ChildProperty.PropType.GetProperty(prop.ChildProperty.EntityProp).SetValue(childEntity,value,null);
prop.ComplexPropType.GetProperty(prop.EntityProp).SetValue(propEntity, childEntity, null);
}
else
{
prop.ComplexPropType.GetProperty(prop.EntityProp).SetValue(propEntity,value,null);
}
//添加到实体中
type.GetProperty(prop.ComplexPropName).SetValue(entity,propEntity,null);
}
else
{
if (prop.ChildProperty != null)
{
var childEntity =
prop.ChildProperty.PropType.Assembly.CreateInstance(prop.ChildProperty.PropType.FullName);
prop.ChildProperty.PropType.GetProperty(prop.ChildProperty.EntityProp).SetValue(childEntity,value,null);
prop.ComplexPropType.GetProperty(prop.EntityProp).SetValue(propEntity, childEntity, null);
}
else
{
prop.ComplexPropType.GetProperty(prop.EntityProp).SetValue(propEntity, value, null);
}
}
}
//设置二维数据类型属性
foreach (var prop in this.SplitProperties)
{
var arrayData = item[prop.Caption].ToString().Split(',');
//创建对应的类型集合
var listType = typeof(List<>).MakeGenericType(prop.ComplexPropType);
var procList = Activator.CreateInstance(listType) as IList;
foreach (var propValue in arrayData)
{
var input = propValue;
//验证格式
string message = "";
if (!prop.ValidateInput(input, ref message))
{
throw new BaseException(message);
}
//获取对应类型的值
var value = prop.GetValue(input);
if (prop.ChildProperty != null)
{
var propEntity = prop.ComplexPropType.Assembly.CreateInstance(prop.ComplexPropType.FullName);
var childEntity =
prop.ChildProperty.PropType.Assembly.CreateInstance(prop.ChildProperty.PropType.FullName);
prop.ChildProperty.PropType.GetProperty(prop.ChildProperty.EntityProp).SetValue(childEntity, value, null);
prop.ComplexPropType.GetProperty(prop.EntityProp).SetValue(propEntity, childEntity, null);
procList.Add(propEntity);
}
else
{
var propEntity = prop.ComplexPropType.Assembly.CreateInstance(prop.ComplexPropType.FullName);
prop.ComplexPropType.GetProperty(prop.EntityProp).SetValue(propEntity, value, null);
procList.Add(propEntity);
}
}
//将集合添加到实体中
type.GetProperty(prop.ComplexPropName).SetValue(entity,procList,null);
}
resultData.Add(entity);
}
return resultData;
}
#endregion
}
}

View File

@@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MyCode.Project.Infrastructure.Exceptions;
namespace MyCode.Project.Infrastructure.Imports
{
/// <summary>
/// 导入Excel数据任务
/// </summary>
public class ImportExcelProcess<T>:IImportExcelProcess where T:class ,new()
{
/// <summary>
/// 导入数据对应的配置实体
/// </summary>
public ImportConfig<T> Config { get; protected set; }
/// <summary>
/// 导入数据方法
/// </summary>
private ImportEvent<T> ImportFunc;
/// <summary>
/// 获取数据方法
/// </summary>
private GetDataEvent<T> GetDataFunc;
/// <summary>
/// 初始化一个<see cref="ImportExcelProcess{T}"/>类型的实例
/// </summary>
/// <param name="config">导入配置</param>
/// <param name="func">导入方法</param>
public ImportExcelProcess(ImportConfig<T> config, ImportEvent<T> func)
{
this.Config = config;
this.ImportFunc = func;
}
/// <summary>
/// 初始化一个<see cref="ImportExcelProcess{T}"/>类型的实例
/// </summary>
/// <param name="config">导入配置</param>
/// <param name="func">获取数据方法</param>
public ImportExcelProcess(ImportConfig<T> config, GetDataEvent<T> func)
{
this.Config = config;
this.GetDataFunc = func;
}
#region RunImportExcelProcess(Excel数据的方法)
/// <summary>
/// 执行导入Excel数据的方法
/// </summary>
public ImportResult RunImportExcelProcess()
{
if (ImportFunc == null) { throw new BaseException("没有找到导入数据的方法!"); }
ImportResult result=new ImportResult();
var msg = "";
//验证是否字段都有
if (!this.Config.ValidFormat(ref msg)) { throw new BaseException(msg); }
//获取Excel数据
var sourceData = this.Config.ExcelUtil.ExcelToList();
//将对象转成List<T>
var resultData = this.Config.GetListData(sourceData);
//执行导入的方法
var tmpResult = this.ImportFunc(resultData);
var importResult = tmpResult as ImportResult;
if (importResult != null)
{
result.InsertCount += importResult.InsertCount;
result.UpdateCount += (tmpResult as ImportResult).UpdateCount;
}
return result;
}
#endregion
#region GetImportExcelData(Excel数据的方法)
/// <summary>
/// 获取导入Excel数据的方法
/// </summary>
public List<object> GetImportExcelData()
{
if (GetDataFunc == null) { throw new BaseException("没有找到导入数据的方法!"); }
var msg = "";
if (!this.Config.ValidFormat(ref msg))
{
throw new BaseException(msg);
}
//获取Excel数据
var sourceData = this.Config.ExcelUtil.ExcelToList();
List<object> result = new List<object>();
var resultData = this.Config.GetListData(sourceData);
if (resultData != null)
{
var tmpResult = this.GetDataFunc(resultData);
if (tmpResult != null)
{
result.AddRange(tmpResult);
}
else
{
return result;
}
}
else
{
return result;
}
return result;
}
#endregion
}
}

View File

@@ -0,0 +1,61 @@
/************************************************************************************
* Copyright (c) 2017 All Rights Reserved.
* CLR版本4.0.30319.42000
* 机器名称JIAN
* 命名空间MyCode.Project.Infrastructure.Imports
* 文件名ImportListProperty
* 版本号v1.0.0.0
* 唯一标识7ee2c39b-a61c-4851-ae9f-67f24d552148
* 当前的用户域JIAN
* 创建人:简玄冰
* 电子邮箱jianxuanhuo1@126.com
* 创建时间2017/6/21 11:48:32
* 描述:
*
* =====================================================================
* 修改标记:
* 修改时间2017/6/21 11:48:32
* 修改人:简玄冰
* 版本号v1.0.0.0
* 描述:
*
/************************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyCode.Project.Infrastructure.Imports
{
/// <summary>
/// 子表数据导入
/// </summary>
public class ImportListProperty:ImportProperty
{
/// <summary>
/// 复杂属性的名称
/// </summary>
public string ComplexPropName { get; set; }
/// <summary>
/// 复杂属性的类型
/// </summary>
public Type ComplexPropType { get; set; }
/// <summary>
/// 子属性类型
/// </summary>
public ImportChildProperty ChildProperty { get; set; }
/// <summary>
/// 主表的主键字段,即唯一标记
/// </summary>
public string PrimaryKey { get; set; }
/// <summary>
/// 主表的主键字段在Excel中的标题即唯一标记
/// </summary>
public string PrimaryKeyCaption { get; set; }
}
}

View File

@@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using MyCode.Project.Infrastructure.Extensions;
namespace MyCode.Project.Infrastructure.Imports
{
/// <summary>
/// 基本类型数据属性类
/// </summary>
public class ImportProperty
{
/// <summary>
/// 标题
/// </summary>
public string Caption { get; set; }
/// <summary>
/// 实体的属性名称
/// </summary>
public string EntityProp { get; set; }
/// <summary>
/// 是否允许为空,默认允许
/// </summary>
public bool IsNullable { get; set; }
/// <summary>
/// 最大长度
/// </summary>
public int MaxLength { get; set; }
/// <summary>
/// 数据类型默认为字符串只有string、int、decimal三个类型其他类型不做检查
/// </summary>
public Type ValueType { get; set; }
public ImportProperty()
{
this.IsNullable = true;
this.ValueType = typeof(string);
}
/// <summary>
/// 验证数据格式是否合法
/// </summary>
/// <param name="input">输入数据</param>
/// <param name="message">错误消息</param>
/// <returns></returns>
public bool ValidateInput(object input, ref string message)
{
if (input == null && this.IsNullable)
{
return true;
}
if (input == null && !this.IsNullable)
{
message=string.Format("[{0}]列不允许为空,必须填写数据!",this.Caption);
return false;
}
var str = input.ToString();
if (string.IsNullOrEmpty(str) && !this.IsNullable)
{
message = string.Format("[{0}]列不允许为空,必须填写数据!", this.Caption);
return false;
}
if (string.IsNullOrEmpty(str) && this.IsNullable)
{
return true;
}
if (str.Length > this.MaxLength && this.MaxLength > 0)
{
message = string.Format("[{0}]列中的[{1}]数据超出最大长度!", this.Caption, input);
return false;
}
if (this.ValueType == typeof(decimal))
{
if (!Regex.IsMatch(str, @"^([0-9]+\.[0-9]+)|[0-9]+$"))
{
message=string.Format("[{0}]列中的[{1}]数据不是合法的数值!",this.Caption,input);
return false;
}
}
if (this.ValueType == typeof(int))
{
if (!Regex.IsMatch(str, @"^[0-9]+$"))
{
message = string.Format("[{0}]列中的[{1}]数据不是合法的整数!", this.Caption, input);
return false;
}
}
if (this.ValueType == typeof(DateTime))
{
DateTime value=DateTime.Now;
if (!DateTime.TryParse(str, out value))
{
message = string.Format("[{0}]列中的[{1}]数据不是合法的时间!", this.Caption, input);
return false;
}
}
return true;
}
/// <summary>
/// 获取对应类型的数据
/// </summary>
/// <param name="input">输入数据</param>
/// <returns></returns>
public object GetValue(object input)
{
if (input == null)
{
return null;
}
if (input.GetType() == this.ValueType)
{
return input;
}
return Convert.ChangeType(input, this.ValueType);
}
}
}

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyCode.Project.Infrastructure.Imports
{
/// <summary>
/// 导入结果实体
/// </summary>
public class ImportResult
{
/// <summary>
/// 新增记录数
/// </summary>
public int InsertCount { get; set; }
/// <summary>
/// 更新记录数
/// </summary>
public int UpdateCount { get; set; }
/// <summary>
/// 补充信息
/// </summary>
public string Msg { get; set; }
}
}

View File

@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyCode.Project.Infrastructure.Imports
{
/// <summary>
/// 二维数据导入
/// </summary>
public class ImportSplitProperty:ImportProperty
{
/// <summary>
/// 复杂属性的名称
/// </summary>
public string ComplexPropName { get; set; }
/// <summary>
/// 复杂属性的类型
/// </summary>
public Type ComplexPropType { get; set; }
/// <summary>
/// 分隔符,默认为逗号
/// </summary>
public char Speparator { get; set; }
/// <summary>
/// 子属性类型
/// </summary>
public ImportChildProperty ChildProperty { get; set; }
/// <summary>
/// 初始化一个<see cref="ImportSplitProperty"/>类型的实例
/// </summary>
public ImportSplitProperty()
{
this.Speparator = ',';
}
}
}