FeiNuo.Core 1.3.4

dotnet add package FeiNuo.Core --version 1.3.4
                    
NuGet\Install-Package FeiNuo.Core -Version 1.3.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FeiNuo.Core" Version="1.3.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FeiNuo.Core" Version="1.3.4" />
                    
Directory.Packages.props
<PackageReference Include="FeiNuo.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FeiNuo.Core --version 1.3.4
                    
#r "nuget: FeiNuo.Core, 1.3.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FeiNuo.Core@1.3.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FeiNuo.Core&version=1.3.4
                    
Install as a Cake Addin
#tool nuget:?package=FeiNuo.Core&version=1.3.4
                    
Install as a Cake Tool

FeiNuo.Core

基于Net10开发,提供NetCore开发常用功能的封装。

  1. 提供常用数据模型;
  2. 提供常用工具类和扩展功能:如JsonUtil,StringExtensions等;
  3. 提供常用组件的封装:如Excel操作,验证码生成等;

一、常用数据模型

1. 实体类基类:

   // 提供操作人,操作时间相关字段,默认实现ICloneable接口,并调用MemberwiseClone实现默认的浅拷贝
   1、BaseDto: CreateBy,CreateTime
   2、BaseEntity:  CreateBy,CreateTime,UpdateBy,UpdateTime

2. 分页模型:

   1、PageResult:  TotalCount(int), DataList(IEnumerable<TEntity>)
   2、Pager: PageNo(int), PageSize(int), SortBy(List<SortItem>)
   3、SortItem: SortField(string), SortType(SortTypeEnum)
   4、SortTypeEnum: ASC,DESC

3. 查询模型

   BaseQuery: 查询基类,提供一个Search模糊搜索条件和时间范围字段StartDate/EndDate
   AbstractQuery: 查询条件抽象类,提借查询条件的封装拼成Linq表达式,方便EF直接调用
   CommonQuery:提供构造函数传入Dictionary<string, StringValues> queryParams,提供快捷方法查询各种类型的查询条件

4. 登录用户LoginUser

    public class LoginUser
    {
        /// <summary>
        /// 用户名
        /// </summary>
        [Description("用户名")]
        public string Username { get; set; } = null!;

        /// <summary>
        /// 姓名/昵称
        /// </summary>
        [Description("姓名/昵称")]
        public string Nickname { get; set; } = string.Empty;

        /// <summary>
        /// 用户密码
        /// </summary>
        [JsonIgnore]
        [Description("用户密码")]
        public string? Password { get; set; }

        /// <summary>
        /// 用户角色
        /// </summary>
        [Description("用户角色")]
        public List<string> Roles { get; set; } = [];

        /// <summary>
        /// 权限字符串
        /// </summary>
        [Description("权限字符串")]
        public List<string> Permissions { get; set; } = [];

        /// <summary>
        /// 其他信息
        /// </summary>
        [Description("其他信息")]
        public string UserData { get; set; } = string.Empty;

        /// <summary>
        /// 请求的客户端信息,方便传参用,有需要时需手动在Controller中赋值 
        /// </summary>
        [Description("请求的客户端信息,方便传参用,有需要时需手动在Controller中赋值 ")]
        public RequestClient? RequestClient { get; set; }

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public LoginUser() { }

        /// <summary>
        /// 根据User.Claims构造用户对象
        /// </summary>
        /// <param name="claims"></param>
        public LoginUser(IEnumerable<Claim> claims) { UserClaims = claims; }

        /// <summary>
        /// 构造函数
        /// roles和permissions字符串中不能有英文逗号
        /// </summary>
        public LoginUser(string username, string nickname, string? password = null, IEnumerable<string>? roles = null, IEnumerable<string>? permissions = null)
        {
            Username = username;
            Nickname = nickname;
            Password = password;
            Roles = [.. (roles ?? [])];
            Permissions = [.. (permissions ?? [])];
        }

        /// <summary>
        /// 是否是超级管理员
        /// </summary>
        public bool IsSuperAdmin
        {
            get
            {
                return Username == AppConstants.SUPER_ADMIN || Roles.Any(t => t == AppConstants.SUPER_ADMIN);
            }
        }

        /// <summary>
        /// 是否有角色
        /// </summary>
        public bool HasRole(string role)
        {
            return Roles.Any(a => a == role);
        }

        /// <summary>
        /// 用户信息和User.Identify.Claims的转换
        /// </summary>
        [JsonIgnore]
        public IEnumerable<Claim> UserClaims
        {
            get
            {
                var claims = new List<Claim>()
                {
                    new (FNClaimTypes.UserName, Username),
                };
                if (!string.IsNullOrWhiteSpace(Nickname))
                {
                    claims.Add(new(FNClaimTypes.NickName, Nickname));
                }
                foreach (var role in Roles)
                {
                    claims.Add(new(FNClaimTypes.Role, role));
                }
                foreach (var perm in Permissions)
                {
                    claims.Add(new(FNClaimTypes.Permission, perm));
                }
                if (!string.IsNullOrEmpty(UserData))
                {
                    claims.Add(new(FNClaimTypes.Data, UserData));
                }
                return claims;
            }
            private set
            {
                if (!value.Any()) return;
                Username = value.SingleOrDefault(a => a.Type == FNClaimTypes.UserName)!.Value;
                Nickname = value.SingleOrDefault(a => a.Type == FNClaimTypes.NickName)?.Value ?? string.Empty;

                Roles = value.Where(a => a.Type == FNClaimTypes.Role || a.Type == ClaimTypes.Role).Select(a => a.Value).Distinct().ToList();
                Permissions = value.Where(a => a.Type == FNClaimTypes.Permission).Select(a => a.Value).Distinct().ToList();

                UserData = value.SingleOrDefault(a => a.Type == FNClaimTypes.Data)?.Value ?? string.Empty;
            }
        }
     }

5. 其他模型

    1、SelectOption: 前端常用的下拉列表选项,提供Lable,Value,Disabled,Color,Data常用字段
    2、RouteVO,MetaVO,MenuVO: Vue路由或菜单对应的实体对象
    3、RequestClient: 封装请求客户端的信息:Ip,Os,Browser,Device
    4、MessageResult: 用于前后端传消息用:Type,Message,Data,Timestamp
    5、ITree:树形结构接口,定义Id,ParentId,Children属性,方便构造树形结构

二、提供常用工具类和扩展功能

1. JsonUtils: 使用System.Text.Json处理序列化,默认添加以下序列化配置

    public static void MergeSerializerOptions(JsonSerializerOptions options)
    {
        // 空值不输出
        options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
        // 阻断循环引用
        options.ReferenceHandler = ReferenceHandler.IgnoreCycles;
        // 设置支持的编码,防止转义
        options.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
        // 小驼峰转换
        options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
        // 支持从字符转成数字
        options.NumberHandling = JsonNumberHandling.AllowReadingFromString;
        // 反序列化不区分大小写
        options.PropertyNameCaseInsensitive = true;
        // JSON格式化配置,日期格式 yyyy-MM-dd HH:mm:ss
        options.Converters.Add(new DateTimeConverter());
        // 可空数字类型转换器
        options.Converters.Add(new NullableConverter<short>());
        options.Converters.Add(new NullableConverter<int>());
        options.Converters.Add(new NullableConverter<decimal>());
        options.Converters.Add(new NullableConverter<DateTime>());
    }

2. DateUtils: 日期相关,目前只定义了两个常用日期常量,其他待添加

  /// <summary>
  /// SQL Server中零日期值,主要用于日期字段的默认值。
  /// </summary>
  public static readonly DateTime ZeroSqlDateTime = new(1900, 1, 1);

  /// <summary>
  /// SQL Server中最大日期值,主要用于查询条件:结束日期
  /// </summary>
  public static readonly DateTime MaxSqlDateTime = new(9999, 1, 1);

3. 常用类的扩展方法

    StringExtensions:
    EnumExtensions:
    DateTimeExtensions:
    ExpressionExtensions:
    QueryableExtensions:   
ServiceInjectionExtensions

自动注入实现BaseService接口的类或者标注Service特性的类。

  builder.Services.AutoInjectServcice();

  对于标注有[Service]特性的类:
  1. 如果特性中有注入类型,则以特性中指定的类型为准
  2. 如果特性中没有注入类型,则根据当前类的类型和当前类实现的接口类型注入
  3. 生命周期默认为 `ServiceLifetime.Scoped`,可以在特性中修改

  实现IService接口或者继承BaseService类的所有类
  1. 如果该类有[Service]特性,按前面规则注入
  2. 有根据当前类的类型和当前类实现的接口类型注入
  3. 注入的生命周期全部为 `ServiceLifetime.Scoped`
  4. 如果默认注入的不合适,可添加[Service]特性自定义

三、提供常用组件功能

部分功能需引入相应的依赖库

1、对NPOI Excel的功能封装

该功能需要此入 NPOI (>=2.7.2)

  1. PoiHelper类封装POI实现,提供Excel常用操作
  2. ExcelStyle类封装常用excel格式,StyleFactory样式工厂类,将相同样式缓存,避免重复重建样式
  3. PoiExcel封装Poi的Workbook,Sheet对象,提供各种方法,快速创建excel,添加标题,数据等
  4. Excel导入接口已封装成公共的RestController: 在FeiNuo.AspNetCore包中
    1. [GET]/api/excel/import/config
    2. [GET]/api/excel/import/template
    3. [GET]/api/excel/import/basicdata
    4. [POST]/api/excel/import
    // 导出excel示例
    [HttpGet("export")]
    [EndpointSummary("导出Excel")]
    public async Task<ActionResult> ExportRoles([FromQuery] RoleQuery query)
    {
        var data = await service.FindDataList(query);
        var excel = PoiHelper.CreateExcel(data,
            new ExcelColumn<RoleDto>("角色编码", r => r.RoleName, 15),
            new ExcelColumn<RoleDto>("角色名称", r => r.RoleName, 15),
            new ExcelColumn<RoleDto>("角色状态", d => d.Disabled ? "作废" : "正常"),
            new ExcelColumn<RoleDto>("备注说明", d => d.Remark, 15, ExcelStyle.WrapStyle),
            new ExcelColumn<RoleDto>("创建时间", r => r.CreateTime, 15, ExcelStyle.DateStyle)
        );
        var bytes = excel.GetExcelBytes();
        return File(bytes, excel.ContentType, $"角色导出{DateTime.Now:yyyyMMddHHmmss}.xlsx");
    }
 // 业务类实现IImportService<T>接口,实现导入相关操作
public class RoleService : BaseService<RoleEntity>, IImportService<RoleEntity>
{
    // 导入关键字,用来匹配对应的服务类,必须唯一
    public string ImportKey => "RoleImport";

    // 导入配置
    public ImportConfig GetImportConfig(Dictionary<string, StringValues> paramMap, LoginUser user)
    {
        var template = new ImportTemplate(
            new ExcelColumnText<RoleEntity>("角色编码", (r, v) => r.RoleCode = v!, 15, true, true),
            new ExcelColumnText<RoleEntity>("角色名称", (r, v) => r.RoleName = v!, 15, true),
            new ExcelColumnText<RoleEntity>("备注说明", (r, v) => r.Remark = v, 25)
            {
                ColumnStyle = ExcelStyle.TextStyle.Wrap()
            }
        );
        return new ImportConfig()
        {
            // 前端页面是否显示导入模板的链接,默认:true
            ShowTemplate = true,
            // 导入模板的链接名称,下载模板的文件名称也是用这个,默认:导入模板.xlsx
            TemplateName = "导入模板.xlsx",
            // 导入模板配置,大部分需要模板的都需要配置,少数完全自定义的可不配置
            ImportTemplate = template,
            // 前端下载模板的方法:如果配置模板则默认:PoiHelper.CreateExcel(template),如果没有配置默认是PoiHelper.CreateExcel()
            GetImportTemplate = () => Task.FromResult(PoiHelper.CreateExcel()),

            // 前端页面是否显示下载基础数据的链接,默认:false
            ShowBasicData = false,
            // 下载基础数据的链接名称,下载基础数据的文件名称也是用这个,默认:基础数据.xlsx
            BasicDataName = "基础数据.xlsx",
            // 前端下载基础数据的方法,默认 () => Task.FromResult(PoiHelper.CreateExcel())
            GetBasicData = () => Task.FromResult(PoiHelper.CreateExcel()),

            // 导入的说明文本,前端展示用,默认  string.Empty;
            ImportRemark = "导入说明:1.角色编码必填且不能重复。2.角色名称必填",

            // 导入所需的角色,默认[]
            AuthRoles = [],

            // 导入前是否保存excel文件
            SaveExcel = false,

            // excel保存路径,默认根路径下Attachment/ExcelImport,配置路径后,
            // 文件会在该路径下创建子路径保存文件 /ImportKey/yyyy-mm/guid/filename.
            SavePath = "Attachment/ExcelImport",
        };
    }

    // 执行导入,数据已从Excel转成lstData
    public Task HandleImport(List<RoleEntity> lstData, Dictionary<string, StringValues> paramMap, LoginUser user)
    {
        throw new NotImplementedException();
    }
}

2、验证码功能封装

该功能需要添加依赖项:SixLabors.ImageSharp.Drawing (>=2.1.5)

系统提供CaptchaUtils工具类直接生成验证码;另外提供配置选项类CaptchaOptions。

如果是发布到linux系统,生成验证码所需的字体文件可添加Fonts文件夹,如果没有设置,系统取默认的actionj字体。

生成的验证码包括文本和图片的base64格式,后续使用需自己实现

3、操作日志定义

  1. OperateLog: 定义操作日志
  2. OperateType: 定义操作类型
  3. ILogService: 定义操作接口:保存日志用
  4. SimpleLogService:默认日志实现类,通过Logger输出

4、EFCore相关功能

该功能需要添加依赖项:Microsoft.EntityFrameworkCore (>=10.0.0); 如果使用DTO相关的基类,还需依赖Mapster(>=7.4.0)。

  1. PageHelper提供分页排序相关静态方法
  2. 提供BaseService<Entity>提供常用的实体查询方法,不使用DTO,直接查询实体类
  3. 提供BaseDtoService<Entity>提供常用的查询方法(泛型),并将查询结果转成泛型DTO类
  4. 提供BaseDtoService<Entity,Dto>提供常用的查询方法,并将查询结果转成Dto类
  5. 提供BaseDtoService<Entity,TSingleDto,TListDto>,默认查询结果单个数据的转成TSingleDto类型,查集合的数据转成TListDto类型.

5、绑定配置数据

该功能需要添加依赖项:Microsoft.Extensions.Configuration.Binder (>=10.0.0); 业务类继承BaseConfig类,并实现ConfigKey属性,指定配置节的key值,BaseConfig构造函数会自动绑定对应的配置节到当前对象。

public abstract class BaseConfig : BaseService
   {
       public abstract string ConfigKey { get; }

       #region IConfiguration中的方法
       private readonly IConfiguration _configuration;
       public BaseConfig(IConfiguration _configuration)
       {
           this._configuration = _configuration;
           _configuration.GetSection(ConfigKey).Bind(this);
       }

       /// <summary>
       /// 绑定指定key的配置节到对象
       /// </summary>
       /// <typeparam name="T"></typeparam>
       /// <param name="key"></param>
       /// <returns></returns>
       public T GetSection<T>(string key) where T : new()
       {
           var t = new T();
           _configuration.GetSection(key).Bind(t);
           return t;
       }

       /// <summary>
       /// 获取配置值
       /// </summary>
       /// <typeparam name="T"></typeparam>
       /// <param name="key"></param>
       /// <returns></returns>
       public T? GetValue<T>(string key)
       {
           return _configuration.GetValue<T>(key);
       }

       public string? GetConnectionString(string name)
       {
           return _configuration.GetConnectionString(name);
       }
       #endregion

       /// <summary>
       /// 系统编码:FeiNuo:AppCode
       /// </summary>
       public string AppCode { get; set; } = "FeiNuo";

       /// <summary>
       /// 系统名称:FeiNuo:AppName
       /// </summary>
       public string AppName { get; set; } = "菲诺";

       /// <summary>
       /// 版本号:FeiNuo:AppVersion
       /// </summary>
       public string AppVersion { get; set; } = "1.3.3";
   }

   public class FeiNuoConfig : BaseConfig
   {
       public override string ConfigKey => "FeiNuo";
       public FeiNuoConfig(IConfiguration configuration) : base(configuration)
       {
       }
   }
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on FeiNuo.Core:

Package Downloads
FeiNuo.AspNetCore

FeiNuo Web基础库(个人用)

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.3.4 156 2/5/2026
1.3.3 126 1/31/2026
1.3.2 140 1/31/2026
1.3.1 149 1/31/2026 1.3.1 is deprecated because it is no longer maintained.
1.3.0 224 9/20/2025
1.2.1 221 9/10/2025
1.2.0 223 9/4/2025
1.1.16 350 6/13/2025
1.1.15 220 5/21/2025
1.1.13 232 5/20/2025
1.1.12 220 5/19/2025
1.1.11 222 5/19/2025
1.1.10 288 5/15/2025
1.1.9 225 5/9/2025
1.1.8 305 5/9/2025 1.1.8 is deprecated because it has critical bugs.
1.1.7 222 5/8/2025
1.1.6 191 4/19/2025
1.1.5 213 4/19/2025 1.1.5 is deprecated because it has critical bugs.
1.1.4 249 4/18/2025
1.1.3 256 4/7/2025
Loading failed

1.3.3 添加BaseConfig,方便绑定配置项