752 lines
29 KiB
C#
752 lines
29 KiB
C#
using Microsoft.AspNetCore.Http;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using OfficeOpenXml;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
using System.ComponentModel.DataAnnotations;
|
||
using System.Globalization;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Linq.Expressions;
|
||
using System.Reflection;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using VOL.Core.Extensions;
|
||
using VOL.Core.Services;
|
||
using VOL.Entity.Enum;
|
||
|
||
namespace VOL.Core.Utilities
|
||
{
|
||
public static class Tool
|
||
{
|
||
public static string Upload(IFormFile file, string filePath)
|
||
{
|
||
string fullPath = filePath.MapPath(true);
|
||
//string fileName = $"{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.{file.FileName.Split(".")[1]}";
|
||
|
||
//string fileName = file.FileName.Split(".")[0];
|
||
|
||
try
|
||
{
|
||
if (!Directory.Exists(fullPath)) Directory.CreateDirectory(fullPath);
|
||
|
||
if (File.Exists(file.FileName))
|
||
File.Delete(file.FileName);
|
||
using (var stream = new FileStream(fullPath + file.FileName, FileMode.Create))
|
||
{
|
||
file.CopyTo(stream);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Logger.Error($"上传文件失败:Tool.Upload,路径:{filePath},失败文件:{file},{ex.Message + ex.StackTrace}");
|
||
}
|
||
return $"{filePath}{file.FileName}";
|
||
}
|
||
//public static void BatchUpload(List<IFormFile> files, string filePath)
|
||
//{
|
||
// string fullPath = filePath.MapPath(true);
|
||
// //string fileName = $"{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.{file.FileName.Split(".")[1]}";
|
||
// try
|
||
// {
|
||
// if (!Directory.Exists(fullPath)) Directory.CreateDirectory(fullPath);
|
||
|
||
// foreach (var file in files)
|
||
// {
|
||
// string fileName = file.FileName.Split(".")[0];
|
||
|
||
// if (File.Exists(fileName))
|
||
// File.Delete(fileName);
|
||
// using (var stream = new FileStream(fullPath + fileName, FileMode.Create))
|
||
// {
|
||
// file.CopyTo(stream);
|
||
// }
|
||
// }
|
||
// }
|
||
// catch (Exception ex)
|
||
// {
|
||
// Logger.Error($"上传文件失败:Tool.Upload,路径:{filePath},失败文件:{files},{ex.Message + ex.StackTrace}");
|
||
// }
|
||
// //return $"{filePath}{fileName}{file.FileName.Split(".")[1]}";
|
||
//}
|
||
|
||
public static byte[] UploadFile(IFormFile file)
|
||
{
|
||
if (file != null && file.Length > 0)
|
||
{
|
||
using (var memoryStream = new MemoryStream())
|
||
{
|
||
file.CopyTo(memoryStream);
|
||
var fileData = memoryStream.ToArray();
|
||
|
||
return fileData;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
throw new Exception("未选择文件或文件大小为零。");
|
||
}
|
||
}
|
||
|
||
public static byte[] ExportToExcel<T>(Dictionary<string, List<T>> sheetDataList, List<string> fields)
|
||
{
|
||
using (var package = new ExcelPackage(new FileInfo("filename.xlsx")))
|
||
{
|
||
var sheetCount = sheetDataList.Count;
|
||
|
||
foreach (var sheet in sheetDataList)
|
||
{
|
||
var sheetData = sheetDataList[sheet.Key];
|
||
var sheetName = sheet.Key;
|
||
|
||
var worksheet = package.Workbook.Worksheets.Add(sheetName);
|
||
ConfigureWorksheet<T>(worksheet, sheetData, fields);
|
||
}
|
||
|
||
return package.GetAsByteArray();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通用导入Excel
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <param name="fileStream"></param>
|
||
/// <returns></returns>
|
||
public static List<T> ConvertExcelToList<T>(Stream fileStream) where T : new()
|
||
{
|
||
var result = new List<T>();
|
||
|
||
using (var package = new ExcelPackage(fileStream))
|
||
{
|
||
var worksheet = package.Workbook.Worksheets[1]; // 第一个工作表
|
||
|
||
if (worksheet.Dimension == null)
|
||
throw new InvalidOperationException("工作表中没有任何数据。");
|
||
|
||
// 获取表头(第一行)
|
||
var headerRow = worksheet.Cells[1, 1, 1, worksheet.Dimension.End.Column];
|
||
var headers = headerRow.Select(cell => cell.Text?.Trim()).ToList();
|
||
|
||
// 获取实体属性与显示名称的映射
|
||
var displayNameToPropertyMap = GetDisplayNameToPropertyMap<T>();
|
||
|
||
// 从第二行开始解析数据
|
||
for (int row = 2; row <= worksheet.Dimension.End.Row; row++)
|
||
{
|
||
var dataObject = new T();
|
||
|
||
for (int col = 1; col <= worksheet.Dimension.End.Column; col++)
|
||
{
|
||
var header = headers[col - 1];
|
||
if (string.IsNullOrEmpty(header))
|
||
continue;
|
||
|
||
if (!displayNameToPropertyMap.TryGetValue(header, out var property))
|
||
continue; // 找不到对应属性,忽略该列
|
||
|
||
try
|
||
{
|
||
var cellValue = worksheet.Cells[row, col].GetValue<object>();
|
||
var propertyType = property.PropertyType;
|
||
|
||
// ----- 日期类型处理(支持 DateTime / DateTime?)-----
|
||
if (propertyType == typeof(DateTime) || propertyType == typeof(DateTime?))
|
||
{
|
||
DateTime? parsedDate = null;
|
||
|
||
// 情况1:Excel 日期存储为 OADate 数字
|
||
if (cellValue is double numericValue)
|
||
{
|
||
parsedDate = DateTime.FromOADate(numericValue);
|
||
}
|
||
// 情况2:字符串格式的日期
|
||
else if (cellValue is string dateStr && !string.IsNullOrWhiteSpace(dateStr))
|
||
{
|
||
// 支持多种常见日期格式
|
||
string[] formats = new[]
|
||
{
|
||
"yyyy/M/d", // 2025/4/28
|
||
"yyyy/MM/dd", // 2025/04/28
|
||
"M/d/yyyy", // 4/28/2025
|
||
"yyyy-MM-dd", // 2025-04-28
|
||
"dd/MM/yyyy", // 28/04/2025
|
||
"yyyyMMdd", // 20250428
|
||
"d/M/yyyy" // 28/4/2025
|
||
};
|
||
|
||
if (DateTime.TryParseExact(dateStr, formats, CultureInfo.InvariantCulture,
|
||
DateTimeStyles.None, out DateTime dt))
|
||
{
|
||
parsedDate = dt;
|
||
}
|
||
else if (DateTime.TryParse(dateStr, out dt)) // 兜底尝试系统解析
|
||
{
|
||
parsedDate = dt;
|
||
}
|
||
else
|
||
{
|
||
throw new InvalidCastException($"无法将字符串 '{dateStr}' 转换为有效的日期。");
|
||
}
|
||
}
|
||
// 情况3:已经是 DateTime 实例(极少情况)
|
||
else if (cellValue is DateTime dtValue)
|
||
{
|
||
parsedDate = dtValue;
|
||
}
|
||
|
||
// 根据属性是否可空赋值
|
||
if (propertyType == typeof(DateTime))
|
||
{
|
||
if (parsedDate.HasValue)
|
||
property.SetValue(dataObject, parsedDate.Value);
|
||
else
|
||
throw new InvalidCastException($"单元格值为空,无法赋给非空 DateTime 属性 '{property.Name}'。");
|
||
}
|
||
else // DateTime?
|
||
{
|
||
property.SetValue(dataObject, parsedDate);
|
||
}
|
||
|
||
// 日期处理完成,跳过后续通用类型转换
|
||
continue;
|
||
}
|
||
|
||
// ----- 其他类型(int, double, string, bool, 枚举等)-----
|
||
if (cellValue != null)
|
||
{
|
||
// 目标类型是枚举
|
||
if (propertyType.IsEnum)
|
||
{
|
||
// 尝试按字符串或数值转换
|
||
if (cellValue is string enumStr)
|
||
cellValue = Enum.Parse(propertyType, enumStr, true);
|
||
else
|
||
cellValue = Enum.ToObject(propertyType, Convert.ChangeType(cellValue, Enum.GetUnderlyingType(propertyType)));
|
||
}
|
||
else
|
||
{
|
||
// 常规类型转换(如 string -> int, double -> int 等)
|
||
cellValue = Convert.ChangeType(cellValue, propertyType);
|
||
}
|
||
property.SetValue(dataObject, cellValue);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw new InvalidCastException(
|
||
$"行 {row} 列 {col}(列名: {header}):转换 Excel 单元格值 '{worksheet.Cells[row, col].Text}' 到属性 '{property.Name}' 失败。",
|
||
ex);
|
||
}
|
||
}
|
||
|
||
result.Add(dataObject);
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
private static Dictionary<string, PropertyInfo> GetDisplayNameToPropertyMap<T>()
|
||
{
|
||
var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||
var dict = new Dictionary<string, PropertyInfo>(StringComparer.OrdinalIgnoreCase);
|
||
|
||
foreach (var prop in properties)
|
||
{
|
||
// 优先获取 DisplayAttribute 的 Name
|
||
var displayAttr = prop.GetCustomAttribute<DisplayAttribute>();
|
||
if (displayAttr != null && !string.IsNullOrEmpty(displayAttr.Name))
|
||
{
|
||
dict[displayAttr.Name] = prop;
|
||
continue;
|
||
}
|
||
|
||
// 其次获取 DisplayNameAttribute
|
||
var displayNameAttr = prop.GetCustomAttribute<DisplayNameAttribute>();
|
||
if (displayNameAttr != null && !string.IsNullOrEmpty(displayNameAttr.DisplayName))
|
||
{
|
||
dict[displayNameAttr.DisplayName] = prop;
|
||
continue;
|
||
}
|
||
|
||
// 最后使用属性原名
|
||
dict[prop.Name] = prop;
|
||
}
|
||
|
||
return dict;
|
||
}
|
||
|
||
private static Dictionary<string, string> GetDisplayNames<T>()
|
||
{
|
||
var displayNames = new Dictionary<string, string>();
|
||
var properties = typeof(T).GetProperties();
|
||
foreach (var property in properties)
|
||
{
|
||
var displayNameAttribute = property.GetCustomAttribute<DisplayAttribute>();
|
||
if (displayNameAttribute != null)
|
||
{
|
||
var propertyName = property.Name;
|
||
var displayName = displayNameAttribute.Name;
|
||
displayNames[propertyName] = displayName;
|
||
}
|
||
}
|
||
return displayNames;
|
||
}
|
||
/// <summary>
|
||
/// 导出Excel
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <param name="worksheet"></param>
|
||
/// <param name="sheetData"></param>
|
||
/// <param name="fields"></param>
|
||
private static void ConfigureWorksheet<T>(ExcelWorksheet worksheet, IEnumerable<T> sheetData, List<string> fields)
|
||
{
|
||
// 添加表头
|
||
for (int i = 0; i < fields.Count; i++)
|
||
{
|
||
var fieldName = fields[i];
|
||
var displayName = GetDisplayName<T>(fieldName);
|
||
|
||
worksheet.Cells[1, i + 1].Value = displayName;
|
||
}
|
||
|
||
// 添加数据行
|
||
var dataList = sheetData.ToList();
|
||
for (int rowIndex = 0; rowIndex < dataList.Count; rowIndex++)
|
||
{
|
||
var rowData = dataList[rowIndex];
|
||
for (int colIndex = 0; colIndex < fields.Count; colIndex++)
|
||
{
|
||
var fieldName = fields[colIndex];
|
||
var value = GetPropertyValue(rowData, fieldName);
|
||
|
||
// 设置值时处理日期时间
|
||
if (value is DateTime dateTimeValue)
|
||
{
|
||
worksheet.Cells[rowIndex + 2, colIndex + 1].Value = dateTimeValue;
|
||
worksheet.Cells[rowIndex + 2, colIndex + 1].Style.Numberformat.Format = "yyyy-mm-dd hh:mm:ss";
|
||
}
|
||
else
|
||
{
|
||
worksheet.Cells[rowIndex + 2, colIndex + 1].Value = value;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 自动调整列宽
|
||
worksheet.Cells.AutoFitColumns();
|
||
}
|
||
private static string GetDisplayName<T>(string propertyName)
|
||
{
|
||
var property = typeof(T).GetProperty(propertyName);
|
||
if (property != null)
|
||
{
|
||
var displayNameAttribute = property.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault() as DisplayAttribute;
|
||
if (displayNameAttribute != null)
|
||
{
|
||
return displayNameAttribute.Name;
|
||
}
|
||
}
|
||
|
||
return propertyName;
|
||
}
|
||
private static object GetPropertyValue<T>(T obj, string propertyName)
|
||
{
|
||
var property = typeof(T).GetProperty(propertyName);
|
||
return property?.GetValue(obj);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取类中所有得列名
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <returns></returns>
|
||
public static List<string> GetPropertyNames<T>()
|
||
{
|
||
var propertyNames = new List<string>();
|
||
var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||
|
||
foreach (var property in properties)
|
||
{
|
||
// 获取属性上的 DisplayAttribute 特性
|
||
var displayAttribute = property.GetCustomAttribute<DisplayAttribute>();
|
||
|
||
// 检查 DisplayAttribute 特性的名称是否为 "IgnoreColumnAttribute",如果是,则忽略该属性
|
||
if (displayAttribute != null && displayAttribute.Name.ToLower() == "ignorecolumnattribute")
|
||
{
|
||
continue;
|
||
}
|
||
|
||
propertyNames.Add(property.Name);
|
||
}
|
||
|
||
return propertyNames;
|
||
}
|
||
|
||
public static string NumberToChinese(this int number)
|
||
{
|
||
// 定义中文数字数组
|
||
string[] chineseNumbers = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
|
||
|
||
// 如果数字在 0 到 9 之间,则直接返回中文数字
|
||
if (number >= 0 && number <= 9)
|
||
{
|
||
return chineseNumbers[number];
|
||
}
|
||
else
|
||
{
|
||
// 如果数字不在 0 到 9 之间,则抛出异常
|
||
throw new ArgumentOutOfRangeException(nameof(number), "Number must be between 0 and 9.");
|
||
}
|
||
}
|
||
|
||
public static string IncrementId(string maxId)
|
||
{
|
||
// 获取当前日期的前缀(年年年年+月月+日日)
|
||
string datePrefix = DateTime.Now.ToString("yyyyMMdd");
|
||
|
||
// 提取后4位编号部分
|
||
string numberPart = maxId.Substring(maxId.Length - 4);
|
||
|
||
// 将编号部分转为整数并加1
|
||
if (!int.TryParse(numberPart, out int number))
|
||
{
|
||
throw new InvalidOperationException("编号部分格式不正确,应为数字");
|
||
}
|
||
|
||
// 检查编号是否超出范围
|
||
if (number >= 9999)
|
||
{
|
||
throw new InvalidOperationException("编号已达到最大值");
|
||
}
|
||
|
||
// 返回新的编号,保持当前日期前缀和递增后的编号
|
||
return $"{datePrefix}{(number + 1):D4}";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取集合中位数
|
||
/// </summary>
|
||
/// <param name="values"></param>
|
||
/// <returns></returns>
|
||
public static double Median(this List<float> values)
|
||
{
|
||
var sortedValues = values.OrderBy(x => x).ToList();
|
||
int count = sortedValues.Count;
|
||
if (count % 2 == 0)
|
||
{
|
||
return (sortedValues[count / 2 - 1] + sortedValues[count / 2]) / 2.0;
|
||
}
|
||
else
|
||
{
|
||
return sortedValues[count / 2];
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取集合中位数
|
||
/// </summary>
|
||
/// <param name="values"></param>
|
||
/// <returns></returns>
|
||
public static double? Median(this List<double?> values)
|
||
{
|
||
// 过滤掉 null 值
|
||
var sortedValues = values.Where(x => x.HasValue)
|
||
.Select(x => x.Value)
|
||
.OrderBy(x => x)
|
||
.ToList();
|
||
|
||
// 如果列表为空,返回 null
|
||
if (sortedValues.Count == 0)
|
||
return null;
|
||
|
||
int count = sortedValues.Count;
|
||
|
||
// 计算中位数
|
||
if (count % 2 == 0)
|
||
{
|
||
return (sortedValues[count / 2 - 1] + sortedValues[count / 2]) / 2.0;
|
||
}
|
||
else
|
||
{
|
||
return sortedValues[count / 2];
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 获取取样时间
|
||
/// </summary>
|
||
/// <param name="input"></param>
|
||
/// <returns></returns>
|
||
/// <exception cref="ArgumentException"></exception>
|
||
public static DateTime GetDateTimeFromFixedAsh(this string input)
|
||
{
|
||
string timePart;
|
||
|
||
// 判断字符串中是否包含 '-',以确定截取的位置
|
||
int dashIndex = input.IndexOf('-');
|
||
if (dashIndex != -1)
|
||
{
|
||
// 截取 '-' 之前的部分
|
||
timePart = input.Substring(6, dashIndex - 6);
|
||
}
|
||
else
|
||
{
|
||
// 如果没有 '-',则直接截取后面的8位数字
|
||
timePart = input.Substring(6, 8);
|
||
}
|
||
|
||
// 将截取的时间字符串转换为 DateTime 类型
|
||
DateTime result;
|
||
if (DateTime.TryParseExact(timePart, "yyyyMMdd", null, System.Globalization.DateTimeStyles.None, out result))
|
||
{
|
||
return result;
|
||
}
|
||
else
|
||
{
|
||
throw new ArgumentException("时间转换失败");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取枚举所有描述
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <typeparam name="TEnum"></typeparam>
|
||
/// <param name="createItemFunc"></param>
|
||
/// <returns></returns>
|
||
public static List<T> GetEnumDescriptions<T, TEnum>(Func<int, string, T> createItemFunc) where TEnum : Enum
|
||
{
|
||
var enumDescriptions = new List<T>();
|
||
|
||
foreach (TEnum value in Enum.GetValues(typeof(TEnum)))
|
||
{
|
||
int intValue = Convert.ToInt32(value);
|
||
if (intValue >= 1)
|
||
{
|
||
var descriptionAttribute = value.GetType()
|
||
.GetField(value.ToString())
|
||
.GetCustomAttributes(typeof(DescriptionAttribute), false)
|
||
.FirstOrDefault() as DescriptionAttribute;
|
||
|
||
if (descriptionAttribute != null)
|
||
{
|
||
var item = createItemFunc(intValue, descriptionAttribute.Description);
|
||
enumDescriptions.Add(item);
|
||
}
|
||
}
|
||
}
|
||
|
||
return enumDescriptions;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取枚举描述
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
/// <returns></returns>
|
||
public static string GetDescription(this Enum value)
|
||
{
|
||
if (value == null)
|
||
{
|
||
throw new ArgumentNullException(nameof(value), "Enum value cannot be null");
|
||
}
|
||
|
||
// 获取字段信息
|
||
FieldInfo field = value.GetType().GetField(value.ToString());
|
||
|
||
if (field == null)
|
||
{
|
||
// 如果字段信息为空,返回默认的描述
|
||
return "";
|
||
}
|
||
|
||
// 获取 DescriptionAttribute 特性
|
||
var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||
var attribute = attributes.FirstOrDefault() as DescriptionAttribute;
|
||
|
||
// 如果特性为空,返回空字符串
|
||
return attribute?.Description ?? "";
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 测试类型枚举转换
|
||
/// </summary>
|
||
/// <param name="itemCode"></param>
|
||
/// <returns></returns>
|
||
//public static CategoryEnumType? GetCategoryEnumTypeByItemCode(string itemCode)
|
||
//{
|
||
// if (Enum.TryParse(typeof(Ai_CategoryEnumType), itemCode, true, out var aiCategoryEnum))
|
||
// {
|
||
// var aiCategoryName = Enum.GetName(typeof(Ai_CategoryEnumType), aiCategoryEnum);
|
||
// if (Enum.TryParse(typeof(CategoryEnumType), aiCategoryName, true, out var categoryEnum))
|
||
// {
|
||
// return (CategoryEnumType)categoryEnum;
|
||
// }
|
||
// }
|
||
// return null; // 如果找不到对应的映射值,返回 null 或者抛出异常
|
||
//}
|
||
|
||
public static byte[] DicExportToExcel(Dictionary<string, List<Dictionary<string, string>>> sheetDataList)
|
||
{
|
||
using (var package = new ExcelPackage())
|
||
{
|
||
foreach (var sheet in sheetDataList)
|
||
{
|
||
var sheetName = sheet.Key;
|
||
var sheetData = sheet.Value;
|
||
|
||
var worksheet = package.Workbook.Worksheets.Add(sheetName);
|
||
DicConfigureWorksheet(worksheet, sheetData);
|
||
}
|
||
|
||
return package.GetAsByteArray();
|
||
}
|
||
}
|
||
private static void DicConfigureWorksheet(ExcelWorksheet worksheet, List<Dictionary<string, string>> sheetData)
|
||
{
|
||
// 假设所有字典在List中都有相同的Key集合,我们可以从第一个元素获取表头
|
||
if (sheetData.Count > 0)
|
||
{
|
||
int rowIndex = 1; // 从第一行开始
|
||
var firstRow = sheetData[0];
|
||
|
||
// 添加表头
|
||
int columnIndex = 1; // 从第一列开始
|
||
foreach (var header in firstRow)
|
||
{
|
||
worksheet.Cells[1, columnIndex++].Value = header.Key;
|
||
}
|
||
|
||
// 添加数据行
|
||
foreach (var rowDict in sheetData)
|
||
{
|
||
rowIndex++;
|
||
columnIndex = 1; // 重置列索引
|
||
foreach (var cell in rowDict)
|
||
{
|
||
worksheet.Cells[rowIndex, columnIndex].Value = cell.Value;
|
||
|
||
// 检查是否需要设置日期时间格式
|
||
if (DateTime.TryParse(cell.Value, out DateTime dateTimeValue))
|
||
{
|
||
worksheet.Cells[rowIndex, columnIndex].Style.Numberformat.Format = "yyyy-mm-dd hh:mm:ss";
|
||
}
|
||
columnIndex++;
|
||
}
|
||
}
|
||
|
||
// 自动调整列宽
|
||
worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns();
|
||
}
|
||
}
|
||
|
||
public static DateTime GetQuarterStartDate(int quarter, int year)
|
||
{
|
||
return quarter switch
|
||
{
|
||
1 => new DateTime(year, 1, 1),
|
||
2 => new DateTime(year, 4, 1),
|
||
3 => new DateTime(year, 7, 1),
|
||
4 => new DateTime(year, 10, 1),
|
||
_ => throw new ArgumentOutOfRangeException()
|
||
};
|
||
}
|
||
|
||
public static DateTime GetQuarterEndDate(int quarter, int year)
|
||
{
|
||
return quarter switch
|
||
{
|
||
1 => new DateTime(year, 3, 31),
|
||
2 => new DateTime(year, 6, 30),
|
||
3 => new DateTime(year, 9, 30),
|
||
4 => new DateTime(year, 12, 31),
|
||
_ => throw new ArgumentOutOfRangeException()
|
||
};
|
||
}
|
||
|
||
public static IQueryable<T> WhereIF<T>(this IQueryable<T> query, bool condition, Expression<Func<T, bool>> predicate)
|
||
{
|
||
return condition ? query.Where(predicate) : query;
|
||
}
|
||
|
||
/// <summary>
|
||
/// DateTime转时间戳
|
||
/// </summary>
|
||
/// <param name="dateTime"></param>
|
||
/// <returns></returns>
|
||
public static long ToUnixTimeMilliseconds(this DateTime dateTime)
|
||
{
|
||
return new DateTimeOffset(dateTime).ToUnixTimeMilliseconds();
|
||
}
|
||
|
||
public static string GetEnumNameByValue(int value)
|
||
{
|
||
if (Enum.IsDefined(typeof(SportsTestItemType), value))
|
||
{
|
||
return ((SportsTestItemType)value).ToString();
|
||
}
|
||
return ""; // Return an empty string if the value is not defined in the enum
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取分数等级
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <param name="score"></param>
|
||
/// <returns></returns>
|
||
public static string GetRank<T>(this T score) where T : struct, IComparable
|
||
{
|
||
// 将 score 转换为 double 进行比较
|
||
double value = Convert.ToDouble(score);
|
||
|
||
return value switch
|
||
{
|
||
>= 90 => "优秀",
|
||
>= 80 => "良好",
|
||
>= 60 => "及格",
|
||
_ => "不及格"
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据等级名称返回枚举
|
||
/// </summary>
|
||
/// <param name="rankName"></param>
|
||
/// <returns></returns>
|
||
/// <exception cref="ArgumentException"></exception>
|
||
public static AchievementRank GetEnumByRankName(string rankName)
|
||
{
|
||
return rankName switch
|
||
{
|
||
"优秀" => AchievementRank.Excellent,
|
||
"良好" => AchievementRank.Fine,
|
||
"及格" => AchievementRank.Pass,
|
||
"不及格" => AchievementRank.Fail,
|
||
_ => throw new ArgumentException("Invalid rank name", nameof(rankName)) // Throw exception for invalid rank name
|
||
};
|
||
}
|
||
public static string ToChineseNumber(this int number)
|
||
{
|
||
string[] chineseNumbers = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
|
||
|
||
if (number <= 0)
|
||
throw new ArgumentException("Number must be greater than zero.");
|
||
|
||
if (number < 10)
|
||
return chineseNumbers[number];
|
||
|
||
if (number < 20)
|
||
return "十" + (number % 10 == 0 ? "" : chineseNumbers[number % 10]);
|
||
|
||
int tens = number / 10;
|
||
int units = number % 10;
|
||
|
||
return chineseNumbers[tens] + "十" + (units == 0 ? "" : chineseNumbers[units]);
|
||
}
|
||
}
|
||
} |