fajiao
2 years ago
35 changed files with 1466 additions and 0 deletions
@ -0,0 +1,4 @@ |
|||||
|
{ |
||||
|
"$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json", |
||||
|
|
||||
|
} |
@ -0,0 +1,44 @@ |
|||||
|
namespace Cis.Application.Cb; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Cb -> Camera base
|
||||
|
/// </summary>
|
||||
|
public class CbInfo |
||||
|
{ |
||||
|
#region Api Info
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Api 分组名
|
||||
|
/// </summary>
|
||||
|
public const string GroupName = "CameraBase"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Api 分组排序
|
||||
|
/// </summary>
|
||||
|
public const int GroupOrder = 100; |
||||
|
|
||||
|
#endregion Api Info
|
||||
|
|
||||
|
#region Database Info
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 数据库名
|
||||
|
/// </summary>
|
||||
|
public const string DbName = SqlSugarConst.DefaultConfigId; |
||||
|
|
||||
|
#endregion Database Info
|
||||
|
|
||||
|
#region Table Info
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// CbCamera 表名
|
||||
|
/// </summary>
|
||||
|
public const string CbCameraTbName = "cb_camera"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// CbCamera 表描述
|
||||
|
/// </summary>
|
||||
|
public const string CbCameraTbDesc = "相机表"; |
||||
|
|
||||
|
#endregion Table Info
|
||||
|
} |
@ -0,0 +1,44 @@ |
|||||
|
namespace Cis.Application.Cb; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 系统字典类型表
|
||||
|
/// </summary>
|
||||
|
[SugarTable(CbInfo.CbCameraTbName, CbInfo.CbCameraTbDesc)] |
||||
|
[Tenant(CbInfo.DbName)] |
||||
|
public class CbCamera : EntityBase |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 名称
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "名称", Length = 64)] |
||||
|
[Required, MaxLength(64)] |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// ip 地址
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "ip地址", Length = 16)] |
||||
|
[Required, MaxLength(16)] |
||||
|
public string Ip { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 端口
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "端口", Length = 5, DefaultValue = "80")] |
||||
|
[Required, MaxLength(5)] |
||||
|
public string Port { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 账号
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "账号", Length = 32)] |
||||
|
[Required, MaxLength(32)] |
||||
|
public string UserName { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 密码
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "密码", Length = 32)] |
||||
|
[Required, MaxLength(32)] |
||||
|
public string Password { get; set; } |
||||
|
} |
@ -0,0 +1,56 @@ |
|||||
|
using Newtonsoft.Json.Linq; |
||||
|
using System.Runtime.InteropServices; |
||||
|
|
||||
|
namespace Cis.Application.Cb; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 相机服务
|
||||
|
/// </summary>
|
||||
|
[ApiDescriptionSettings(CbInfo.GroupName, Order = CbInfo.GroupOrder)] |
||||
|
public class CbCameraService : IDynamicApiController, ITransient |
||||
|
{ |
||||
|
private readonly SqlSugarRepository<CbCamera> _cbCameraRep; |
||||
|
|
||||
|
public CbCameraService(SqlSugarRepository<CbCamera> cbCameraRep) |
||||
|
{ |
||||
|
_cbCameraRep = cbCameraRep; |
||||
|
} |
||||
|
|
||||
|
public async Task<CbCamera> Get(long id) |
||||
|
{ |
||||
|
CbCamera entity = await _cbCameraRep.GetByIdAsync(id); |
||||
|
return entity; |
||||
|
} |
||||
|
|
||||
|
public async Task<List<CbCamera>> GetList(string queryJson) |
||||
|
{ |
||||
|
JObject queryObj = queryJson.ToJObject(); |
||||
|
List<CbCamera> list = await _cbCameraRep.AsQueryable() |
||||
|
.ToListAsync(); |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
public async Task<List<CbCamera>> GetPageList(string queryJson, string pagination) |
||||
|
{ |
||||
|
Pagination pageObj = pagination.ToObject<Pagination>(); |
||||
|
JObject queryObj = queryJson.ToJObject(); |
||||
|
List<CbCamera> list = await _cbCameraRep.AsQueryable() |
||||
|
.ToPageListAsync(pageObj.Index, pageObj.Size); |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
public async Task Add(CbCamera entity) |
||||
|
{ |
||||
|
await _cbCameraRep.InsertAsync(entity); |
||||
|
} |
||||
|
|
||||
|
public async Task Update(CbCamera entity) |
||||
|
{ |
||||
|
await _cbCameraRep.UpdateAsync(entity); |
||||
|
} |
||||
|
|
||||
|
public async Task Delete(CbCamera entity) |
||||
|
{ |
||||
|
await _cbCameraRep.DeleteAsync(entity); |
||||
|
} |
||||
|
} |
@ -0,0 +1,44 @@ |
|||||
|
namespace Cis.Application.Cm; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Cm -> Camera mark
|
||||
|
/// </summary>
|
||||
|
public class CmInfo |
||||
|
{ |
||||
|
#region Api Info
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Api 分组名
|
||||
|
/// </summary>
|
||||
|
public const string GroupName = "CameraMark"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Api 分组排序
|
||||
|
/// </summary>
|
||||
|
public const int GroupOrder = 100; |
||||
|
|
||||
|
#endregion Api Info
|
||||
|
|
||||
|
#region Database Info
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 数据库名
|
||||
|
/// </summary>
|
||||
|
public const string DbName = SqlSugarConst.DefaultConfigId; |
||||
|
|
||||
|
#endregion Database Info
|
||||
|
|
||||
|
#region Table Info
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// CmMarkGroup 表名
|
||||
|
/// </summary>
|
||||
|
public const string CmMarkGroupTbName = "cm_mark_group"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// CmMarkGroup 表描述
|
||||
|
/// </summary>
|
||||
|
public const string CmMarkGroupTbDesc = "标记分组表"; |
||||
|
|
||||
|
#endregion Table Info
|
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
namespace Cis.Application.Cm; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 标记分组表
|
||||
|
/// </summary>
|
||||
|
[SugarTable(CmInfo.CmMarkGroupTbName, CmInfo.CmMarkGroupTbDesc)] |
||||
|
[Tenant(CmInfo.DbName)] |
||||
|
public class CmMarkGroup : EntityBase |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 名称
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "名称", Length = 64)] |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 排序
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "排序")] |
||||
|
public int Order { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 备注
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "备注", Length = 256)] |
||||
|
[MaxLength(256)] |
||||
|
public string Remark { get; set; } |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
namespace Cis.Application.Cm; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 标记分组服务
|
||||
|
/// </summary>
|
||||
|
[ApiDescriptionSettings(CmInfo.GroupName, Order = CmInfo.GroupOrder)] |
||||
|
public class CmMarkGroupService : IDynamicApiController, ITransient |
||||
|
{ |
||||
|
private readonly SqlSugarRepository<CmMarkGroup> _cmMarkGroupRep; |
||||
|
|
||||
|
public CmMarkGroupService(SqlSugarRepository<CmMarkGroup> cmMarkGroupRep) |
||||
|
{ |
||||
|
_cmMarkGroupRep = cmMarkGroupRep; |
||||
|
} |
||||
|
} |
@ -0,0 +1,26 @@ |
|||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.AspNetCore.Hosting; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
|
||||
|
namespace Cis.Application; |
||||
|
|
||||
|
[AppStartup(100)] |
||||
|
public class Startup : AppStartup |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 配置应用所需服务,在该方法中可以添加应用所需要的功能或服务
|
||||
|
/// </summary>
|
||||
|
/// <param name="services"></param>
|
||||
|
public void ConfigureServices(IServiceCollection services) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 配置应用请求处理管道
|
||||
|
/// </summary>
|
||||
|
/// <param name="app"></param>
|
||||
|
/// <param name="env"></param>
|
||||
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) |
||||
|
{ |
||||
|
} |
||||
|
} |
@ -0,0 +1,54 @@ |
|||||
|
namespace Cis.Application.Sys; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sys -> System
|
||||
|
/// </summary>
|
||||
|
public class SysInfo |
||||
|
{ |
||||
|
#region Api Info
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Api 分组名
|
||||
|
/// </summary>
|
||||
|
public const string GroupName = "Sys"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Api 分组排序
|
||||
|
/// </summary>
|
||||
|
public const int GroupOrder = 100; |
||||
|
|
||||
|
#endregion Api Info
|
||||
|
|
||||
|
#region Database Info
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 数据库名
|
||||
|
/// </summary>
|
||||
|
public const string DbName = SqlSugarConst.DefaultConfigId; |
||||
|
|
||||
|
#endregion Database Info
|
||||
|
|
||||
|
#region Table Info
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// SysDictType 表名
|
||||
|
/// </summary>
|
||||
|
public const string SysDictTypeTbName = "sys_dict_type"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// SysDictType 表描述
|
||||
|
/// </summary>
|
||||
|
public const string SysDictTypeTbDesc = "系统字典类型表"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// SysDataType 表名
|
||||
|
/// </summary>
|
||||
|
public const string SysDictDataTbName = "sys_data_data"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// SysDataType 表描述
|
||||
|
/// </summary>
|
||||
|
public const string SysDictDataTbDesc = "系统字典值表"; |
||||
|
|
||||
|
#endregion Table Info
|
||||
|
} |
@ -0,0 +1,54 @@ |
|||||
|
namespace Cis.Application.Sys; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 系统字典值表
|
||||
|
/// </summary>
|
||||
|
[SugarTable("sys_dict_data", "系统字典值表")] |
||||
|
public class SysDictData : EntityBase |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 字典类型Id
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "字典类型Id")] |
||||
|
public long DictTypeId { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 字典类型
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(IsIgnore = true)] |
||||
|
[Navigate(NavigateType.OneToOne, nameof(DictTypeId))] |
||||
|
public SysDictType DictType { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 值
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "值", Length = 128)] |
||||
|
[Required, MaxLength(128)] |
||||
|
public string Value { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 编码
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "编码", Length = 64)] |
||||
|
[Required, MaxLength(64)] |
||||
|
public string Code { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 排序
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "排序")] |
||||
|
public int Order { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 备注
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "备注", Length = 128)] |
||||
|
[MaxLength(128)] |
||||
|
public string Remark { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 状态
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "状态")] |
||||
|
public StatusEnum Status { get; set; } = StatusEnum.Enable; |
||||
|
} |
@ -0,0 +1,41 @@ |
|||||
|
namespace Cis.Application.Sys; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 系统字典类型表
|
||||
|
/// </summary>
|
||||
|
[SugarTable(SysInfo.SysDictTypeTbName, SysInfo.SysDictTypeTbDesc)] |
||||
|
public class SysDictType : EntityBase |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 名称
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "名称", Length = 64)] |
||||
|
[Required, MaxLength(64)] |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 编码
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "编码", Length = 64)] |
||||
|
[Required, MaxLength(64)] |
||||
|
public string Code { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 排序
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "排序")] |
||||
|
public int Order { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 备注
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "备注", Length = 256)] |
||||
|
[MaxLength(256)] |
||||
|
public string Remark { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 状态
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "状态")] |
||||
|
public StatusEnum Status { get; set; } = StatusEnum.Enable; |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
namespace Cis.Application.Sys; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 系统字典值服务
|
||||
|
/// </summary>
|
||||
|
[ApiDescriptionSettings(SysInfo.GroupName, Order = SysInfo.GroupOrder)] |
||||
|
public class SysDictDataService : IDynamicApiController, ITransient |
||||
|
{ |
||||
|
private readonly SqlSugarRepository<SysDictData> _sysDictDataRep; |
||||
|
|
||||
|
public SysDictDataService(SqlSugarRepository<SysDictData> sysDictDataRep) |
||||
|
{ |
||||
|
_sysDictDataRep = sysDictDataRep; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
namespace Cis.Application.Sys; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 系统字典类型服务
|
||||
|
/// </summary>
|
||||
|
[ApiDescriptionSettings(SysInfo.GroupName, Order = SysInfo.GroupOrder)] |
||||
|
public class SysDictTypeService : IDynamicApiController, ITransient |
||||
|
{ |
||||
|
private readonly SqlSugarRepository<SysDictType> _sysDictTypeRep; |
||||
|
|
||||
|
public SysDictTypeService(SqlSugarRepository<SysDictType> sysDictTypeRep) |
||||
|
{ |
||||
|
_sysDictTypeRep = sysDictTypeRep; |
||||
|
} |
||||
|
} |
@ -0,0 +1,10 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 非实体表特性
|
||||
|
/// </summary>
|
||||
|
[SuppressSniffer] |
||||
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] |
||||
|
public class NotTableAttribute : Attribute |
||||
|
{ |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
using NewLife.Caching; |
||||
|
|
||||
|
namespace Cis.Core; |
||||
|
|
||||
|
public static class CacheSetup |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 缓存注册(新生命Redis组件)
|
||||
|
/// </summary>
|
||||
|
/// <param name="services"></param>
|
||||
|
public static void AddCache(this IServiceCollection services) |
||||
|
{ |
||||
|
services.AddSingleton<ICache>(options => |
||||
|
{ |
||||
|
var cacheOptions = App.GetOptions<CacheOptions>(); |
||||
|
if (cacheOptions.CacheType == CacheTypeEnum.Redis.ToString()) |
||||
|
{ |
||||
|
var redis = new Redis(); |
||||
|
redis.Init(cacheOptions.RedisConnectionString); |
||||
|
return redis; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return Cache.Default; |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
@ -0,0 +1,51 @@ |
|||||
|
using NewLife.Caching; |
||||
|
|
||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// SqlSugar二级缓存(必须是内存缓存)
|
||||
|
/// </summary>
|
||||
|
public class SqlSugarCache : ICacheService, ISingleton |
||||
|
{ |
||||
|
private static readonly ICache _cache = NewLife.Caching.Cache.Default; |
||||
|
|
||||
|
public void Add<V>(string key, V value) |
||||
|
{ |
||||
|
_cache.Set(key, value); |
||||
|
} |
||||
|
|
||||
|
public void Add<V>(string key, V value, int cacheDurationInSeconds) |
||||
|
{ |
||||
|
_cache.Set(key, value, cacheDurationInSeconds); |
||||
|
} |
||||
|
|
||||
|
public bool ContainsKey<V>(string key) |
||||
|
{ |
||||
|
return _cache.ContainsKey(key); |
||||
|
} |
||||
|
|
||||
|
public V Get<V>(string key) |
||||
|
{ |
||||
|
return _cache.Get<V>(key); |
||||
|
} |
||||
|
|
||||
|
public IEnumerable<string> GetAllKey<V>() |
||||
|
{ |
||||
|
return _cache.Keys; |
||||
|
} |
||||
|
|
||||
|
public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue) |
||||
|
{ |
||||
|
if (!_cache.TryGetValue<V>(cacheKey, out V value)) |
||||
|
{ |
||||
|
value = create(); |
||||
|
_cache.Set(cacheKey, value, cacheDurationInSeconds); |
||||
|
} |
||||
|
return value; |
||||
|
} |
||||
|
|
||||
|
public void Remove<V>(string key) |
||||
|
{ |
||||
|
_cache.Remove(key); |
||||
|
} |
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
public class SqlSugarConst |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 默认数据库标识
|
||||
|
/// </summary>
|
||||
|
public const string DefaultConfigId = "Cis"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 默认表主键
|
||||
|
/// </summary>
|
||||
|
public const string DefaultPrimaryKey = "Id"; |
||||
|
} |
@ -0,0 +1,46 @@ |
|||||
|
{ |
||||
|
"$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json", |
||||
|
"DbConnection": { |
||||
|
"ConnectionConfigs": [ |
||||
|
{ |
||||
|
"ConfigId": "Cis", |
||||
|
"DbType": "MySql", // MySql、SqlServer、Sqlite、Oracle、PostgreSQL、Dm、Kdbndp、Oscar、MySqlConnector、Access |
||||
|
"ConnectionString": "Data Source=127.0.0.1;port=3306;User ID=root;Password=123456;Database=Cis;pooling=true;sslmode=none;CharSet=utf8;", |
||||
|
//"DbType": "Sqlite", |
||||
|
//"ConnectionString": "DataSource=./cis.db", |
||||
|
//"DbType": "PostgreSQL", |
||||
|
//"ConnectionString": "HOST=127.0.0.1;PORT=5432;USER ID=pgsql;PASSWORD=123456;DATABASE=cis;", |
||||
|
"EnableInitDb": false, // 启用库表初始化 |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
"Cache": { |
||||
|
"CacheType": "Redis", // Memory、Redis |
||||
|
"RedisConnectionString": "127.0.0.1:6379;password=123456;db=2" |
||||
|
}, |
||||
|
"SnowId": { |
||||
|
"WorkerId": 5 // 取值范围0~63,默认1 |
||||
|
}, |
||||
|
"SpecificationDocumentSettings": { |
||||
|
"DocumentTitle": "Swagger",//默认标题 |
||||
|
"DefaultGroupName": "Default"//默认分组名称 |
||||
|
}, |
||||
|
"DynamicApiControllerSettings": { |
||||
|
"DefaultRoutePrefix": "api", //默认路由前缀 |
||||
|
"KeepVerb": true, //是否保留动作谓词 |
||||
|
"KeepName": true, //是否保留默认名称 |
||||
|
"LowercaseRoute": false, //小写路由格式 |
||||
|
"AsLowerCamelCase": true, //启用小驼峰命名(首字母小写) |
||||
|
"UrlParameterization": true // 方法参数 |
||||
|
}, |
||||
|
"AppSettings": { |
||||
|
"InjectSpecificationDocument": true // 生产环境是否开启Swagger |
||||
|
}, |
||||
|
"CorsAccessorSettings": { |
||||
|
"WithExposedHeaders": [ |
||||
|
"access-token", |
||||
|
"x-access-token", |
||||
|
"environment" |
||||
|
] |
||||
|
} |
||||
|
} |
@ -0,0 +1,61 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 框架实体基类Id
|
||||
|
/// </summary>
|
||||
|
public abstract class EntityBaseId |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 雪花Id
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "Id", IsPrimaryKey = true, IsIdentity = false)] |
||||
|
public virtual long Id { get; set; } |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 框架实体基类
|
||||
|
/// </summary>
|
||||
|
public abstract class EntityBase : EntityBaseId |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 创建时间
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "创建时间")] |
||||
|
public virtual DateTime? CreateTime { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 更新时间
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "更新时间")] |
||||
|
public virtual DateTime? UpdateTime { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 创建者Id
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "创建者Id")] |
||||
|
public virtual long? CreateUserId { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 修改者Id
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "修改者Id")] |
||||
|
public virtual long? UpdateUserId { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 软删除
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "软删除")] |
||||
|
public virtual bool IsDelete { get; set; } = false; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 业务数据实体基类(数据权限)
|
||||
|
/// </summary>
|
||||
|
public abstract class DataEntityBase : EntityBase |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 创建者部门Id
|
||||
|
/// </summary>
|
||||
|
[SugarColumn(ColumnDescription = "创建者部门Id")] |
||||
|
public virtual long? CreateOrgId { get; set; } |
||||
|
} |
@ -0,0 +1,47 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
public class Pagination |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 当前页
|
||||
|
/// </summary>
|
||||
|
public virtual int Index { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 页码容量
|
||||
|
/// </summary>
|
||||
|
public virtual int Size { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 排序字段
|
||||
|
/// </summary>
|
||||
|
public virtual string Field { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 排序方向
|
||||
|
/// </summary>
|
||||
|
public virtual string Order { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 总记录数
|
||||
|
/// </summary>
|
||||
|
public virtual int Total { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 页码数
|
||||
|
/// </summary>
|
||||
|
public virtual int Number |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
if (Size > 0) |
||||
|
{ |
||||
|
return ((Size % Total) == 0) ? (Size / Total) : ((Size / Total) + 1); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,19 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 缓存类型枚举
|
||||
|
/// </summary>
|
||||
|
public enum CacheTypeEnum |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 内存缓存
|
||||
|
/// </summary>
|
||||
|
[Description("内存缓存")] |
||||
|
Memory, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Redis缓存
|
||||
|
/// </summary>
|
||||
|
[Description("Redis缓存")] |
||||
|
Redis |
||||
|
} |
@ -0,0 +1,19 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 通用状态枚举
|
||||
|
/// </summary>
|
||||
|
public enum StatusEnum |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 停用
|
||||
|
/// </summary>
|
||||
|
[Description("停用")] |
||||
|
Disable = 0, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 启用
|
||||
|
/// </summary>
|
||||
|
[Description("启用")] |
||||
|
Enable = 1, |
||||
|
} |
@ -0,0 +1,141 @@ |
|||||
|
using Newtonsoft.Json.Linq; |
||||
|
using System.Text; |
||||
|
|
||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 对象拓展
|
||||
|
/// </summary>
|
||||
|
[SuppressSniffer] |
||||
|
public static class ObjectExtension |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 判断类型是否实现某个泛型
|
||||
|
/// </summary>
|
||||
|
/// <param name="type">类型</param>
|
||||
|
/// <param name="generic">泛型类型</param>
|
||||
|
/// <returns>bool</returns>
|
||||
|
public static bool HasImplementedRawGeneric(this Type type, Type generic) |
||||
|
{ |
||||
|
// 检查接口类型
|
||||
|
var isTheRawGenericType = type.GetInterfaces().Any(IsTheRawGenericType); |
||||
|
if (isTheRawGenericType) return true; |
||||
|
|
||||
|
// 检查类型
|
||||
|
while (type != null && type != typeof(object)) |
||||
|
{ |
||||
|
isTheRawGenericType = IsTheRawGenericType(type); |
||||
|
if (isTheRawGenericType) return true; |
||||
|
type = type.BaseType; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
|
||||
|
// 判断逻辑
|
||||
|
bool IsTheRawGenericType(Type type) => generic == (type.IsGenericType ? type.GetGenericTypeDefinition() : type); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 将字典转化为QueryString格式
|
||||
|
/// </summary>
|
||||
|
/// <param name="dict"></param>
|
||||
|
/// <param name="urlEncode"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public static string ToQueryString(this Dictionary<string, string> dict, bool urlEncode = true) |
||||
|
{ |
||||
|
return string.Join("&", dict.Select(p => $"{(urlEncode ? p.Key?.UrlEncode() : "")}={(urlEncode ? p.Value?.UrlEncode() : "")}")); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 将字符串URL编码
|
||||
|
/// </summary>
|
||||
|
/// <param name="str"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public static string UrlEncode(this string str) |
||||
|
{ |
||||
|
return string.IsNullOrEmpty(str) ? "" : System.Web.HttpUtility.UrlEncode(str, Encoding.UTF8); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// List转DataTable
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T"></typeparam>
|
||||
|
/// <param name="list"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public static DataTable ToDataTable<T>(this List<T> list) |
||||
|
{ |
||||
|
DataTable result = new(); |
||||
|
if (list.Count > 0) |
||||
|
{ |
||||
|
// result.TableName = list[0].GetType().Name; // 表名赋值
|
||||
|
PropertyInfo[] propertys = list[0].GetType().GetProperties(); |
||||
|
foreach (PropertyInfo pi in propertys) |
||||
|
{ |
||||
|
Type colType = pi.PropertyType; |
||||
|
if (colType.IsGenericType && colType.GetGenericTypeDefinition() == typeof(Nullable<>)) |
||||
|
{ |
||||
|
colType = colType.GetGenericArguments()[0]; |
||||
|
} |
||||
|
if (IsIgnoreColumn(pi)) |
||||
|
continue; |
||||
|
result.Columns.Add(pi.Name, colType); |
||||
|
} |
||||
|
for (int i = 0; i < list.Count; i++) |
||||
|
{ |
||||
|
ArrayList tempList = new(); |
||||
|
foreach (PropertyInfo pi in propertys) |
||||
|
{ |
||||
|
if (IsIgnoreColumn(pi)) |
||||
|
continue; |
||||
|
object obj = pi.GetValue(list[i], null); |
||||
|
tempList.Add(obj); |
||||
|
} |
||||
|
object[] array = tempList.ToArray(); |
||||
|
result.LoadDataRow(array, true); |
||||
|
} |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 对象序列化成Json字符串
|
||||
|
/// </summary>
|
||||
|
/// <param name="obj"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public static string ToJson(this object obj) |
||||
|
{ |
||||
|
return JSON.GetJsonSerializer().Serialize(obj); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Json字符串反序列化成对象
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T"></typeparam>
|
||||
|
/// <param name="json"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public static T ToObject<T>(this string json) |
||||
|
{ |
||||
|
return JSON.GetJsonSerializer().Deserialize<T>(json); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 字串反序列化成linq对象
|
||||
|
/// </summary>
|
||||
|
/// <param name="Json">字串</param>
|
||||
|
/// <returns></returns>
|
||||
|
public static JObject ToJObject(this string Json) |
||||
|
{ |
||||
|
return Json == null ? JObject.Parse("{}") : JObject.Parse(Json.Replace(" ", "")); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 排除SqlSugar忽略的列
|
||||
|
/// </summary>
|
||||
|
/// <param name="pi"></param>
|
||||
|
/// <returns></returns>
|
||||
|
private static bool IsIgnoreColumn(PropertyInfo pi) |
||||
|
{ |
||||
|
var sc = pi.GetCustomAttributes<SugarColumn>(false).FirstOrDefault(u => u.IsIgnore == true); |
||||
|
return sc != null; |
||||
|
} |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
global using Furion; |
||||
|
global using Furion.ConfigurableOptions; |
||||
|
global using Furion.DatabaseAccessor; |
||||
|
global using Furion.DataValidation; |
||||
|
global using Furion.DependencyInjection; |
||||
|
global using Furion.FriendlyException; |
||||
|
global using Furion.JsonSerialization; |
||||
|
global using Furion.UnifyResult; |
||||
|
global using Mapster; |
||||
|
global using Microsoft.AspNetCore.Http; |
||||
|
global using Microsoft.AspNetCore.Mvc; |
||||
|
global using Microsoft.AspNetCore.Mvc.Filters; |
||||
|
global using Microsoft.Extensions.DependencyInjection; |
||||
|
global using SqlSugar; |
||||
|
global using System; |
||||
|
global using System.Collections; |
||||
|
global using System.Collections.Generic; |
||||
|
global using System.ComponentModel; |
||||
|
global using System.ComponentModel.DataAnnotations; |
||||
|
global using System.Data; |
||||
|
global using System.Linq; |
||||
|
global using System.Reflection; |
||||
|
global using System.Threading.Tasks; |
@ -0,0 +1,17 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 缓存配置选项
|
||||
|
/// </summary>
|
||||
|
public sealed class CacheOptions : IConfigurableOptions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 缓存类型
|
||||
|
/// </summary>
|
||||
|
public string CacheType { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Redis连接字符串
|
||||
|
/// </summary>
|
||||
|
public string RedisConnectionString { get; set; } |
||||
|
} |
@ -0,0 +1,20 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 数据库配置选项
|
||||
|
/// </summary>
|
||||
|
public sealed class DbConnectionOptions : IConfigurableOptions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 数据库集合
|
||||
|
/// </summary>
|
||||
|
public List<DbConnectionConfig> ConnectionConfigs { get; set; } |
||||
|
} |
||||
|
|
||||
|
public sealed class DbConnectionConfig : ConnectionConfig |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 启用库表初始化
|
||||
|
/// </summary>
|
||||
|
public bool EnableInitDb { get; set; } |
||||
|
} |
@ -0,0 +1,12 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 雪花Id配置选项
|
||||
|
/// </summary>
|
||||
|
public sealed class SnowIdOptions : IConfigurableOptions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 机器码
|
||||
|
/// </summary>
|
||||
|
public ushort WorkerId { get; set; } |
||||
|
} |
@ -0,0 +1,13 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 自定义实体过滤器接口
|
||||
|
/// </summary>
|
||||
|
public interface IEntityFilter |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 实体过滤器
|
||||
|
/// </summary>
|
||||
|
/// <returns></returns>
|
||||
|
IEnumerable<TableFilterItem<object>> AddEntityFilter(); |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 实体种子数据接口
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TEntity"></typeparam>
|
||||
|
public interface ISqlSugarEntitySeedData<TEntity> |
||||
|
where TEntity : class, new() |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 种子数据
|
||||
|
/// </summary>
|
||||
|
/// <returns></returns>
|
||||
|
IEnumerable<TEntity> HasData(); |
||||
|
} |
@ -0,0 +1,100 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 分页泛型集合
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TEntity"></typeparam>
|
||||
|
public class SqlSugarPagedList<TEntity> |
||||
|
where TEntity : new() |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 页码
|
||||
|
/// </summary>
|
||||
|
public int Page { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 页容量
|
||||
|
/// </summary>
|
||||
|
public int PageSize { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 总条数
|
||||
|
/// </summary>
|
||||
|
public int Total { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 总页数
|
||||
|
/// </summary>
|
||||
|
public int TotalPages { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 当前页集合
|
||||
|
/// </summary>
|
||||
|
public IEnumerable<TEntity> Items { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否有上一页
|
||||
|
/// </summary>
|
||||
|
public bool HasPrevPage { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否有下一页
|
||||
|
/// </summary>
|
||||
|
public bool HasNextPage { get; set; } |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 分页拓展类
|
||||
|
/// </summary>
|
||||
|
public static class SqlSugarPagedExtensions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 分页拓展
|
||||
|
/// </summary>
|
||||
|
/// <param name="entity"></param>
|
||||
|
/// <param name="pageIndex"></param>
|
||||
|
/// <param name="pageSize"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public static SqlSugarPagedList<TEntity> ToPagedList<TEntity>(this ISugarQueryable<TEntity> entity, int pageIndex, int pageSize) |
||||
|
where TEntity : new() |
||||
|
{ |
||||
|
var total = 0; |
||||
|
var items = entity.ToPageList(pageIndex, pageSize, ref total); |
||||
|
var totalPages = (int)Math.Ceiling(total / (double)pageSize); |
||||
|
return new SqlSugarPagedList<TEntity> |
||||
|
{ |
||||
|
Page = pageIndex, |
||||
|
PageSize = pageSize, |
||||
|
Items = items, |
||||
|
Total = total, |
||||
|
TotalPages = totalPages, |
||||
|
HasNextPage = pageIndex < totalPages, |
||||
|
HasPrevPage = pageIndex - 1 > 0 |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 分页拓展
|
||||
|
/// </summary>
|
||||
|
/// <param name="entity"></param>
|
||||
|
/// <param name="pageIndex"></param>
|
||||
|
/// <param name="pageSize"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public static async Task<SqlSugarPagedList<TEntity>> ToPagedListAsync<TEntity>(this ISugarQueryable<TEntity> entity, int pageIndex, int pageSize) |
||||
|
where TEntity : new() |
||||
|
{ |
||||
|
RefAsync<int> total = 0; |
||||
|
var items = await entity.ToPageListAsync(pageIndex, pageSize, total); |
||||
|
var totalPages = (int)Math.Ceiling(total / (double)pageSize); |
||||
|
return new SqlSugarPagedList<TEntity> |
||||
|
{ |
||||
|
Page = pageIndex, |
||||
|
PageSize = pageSize, |
||||
|
Items = items, |
||||
|
Total = total, |
||||
|
TotalPages = totalPages, |
||||
|
HasNextPage = pageIndex < totalPages, |
||||
|
HasPrevPage = pageIndex - 1 > 0 |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// SqlSugar仓储类
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T"></typeparam>
|
||||
|
public class SqlSugarRepository<T> : SimpleClient<T> where T : class, new() |
||||
|
{ |
||||
|
protected ITenant iTenant = null; // 多租户事务
|
||||
|
|
||||
|
public SqlSugarRepository(ISqlSugarClient context = null) : base(context) // 默认值等于null不能少
|
||||
|
{ |
||||
|
iTenant = App.GetService<ISqlSugarClient>().AsTenant(); |
||||
|
base.Context = iTenant.GetConnectionWithAttr<T>(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,159 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
public static class SqlSugarSetup |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Sqlsugar 上下文初始化
|
||||
|
/// </summary>
|
||||
|
/// <param name="services"></param>
|
||||
|
public static void AddSqlSugar(this IServiceCollection services) |
||||
|
{ |
||||
|
var dbOptions = App.GetOptions<DbConnectionOptions>(); |
||||
|
var configureExternalServices = new ConfigureExternalServices |
||||
|
{ |
||||
|
EntityService = (type, column) => // 修改列可空-1、带?问号 2、String类型若没有Required
|
||||
|
{ |
||||
|
if ((type.PropertyType.IsGenericType && type.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) |
||||
|
|| (type.PropertyType == typeof(string) && type.GetCustomAttribute<RequiredAttribute>() == null)) |
||||
|
column.IsNullable = true; |
||||
|
}, |
||||
|
DataInfoCacheService = new SqlSugarCache(), |
||||
|
}; |
||||
|
dbOptions.ConnectionConfigs.ForEach(config => |
||||
|
{ |
||||
|
config.ConfigureExternalServices = configureExternalServices; |
||||
|
config.InitKeyType = InitKeyType.Attribute; |
||||
|
config.IsAutoCloseConnection = true; |
||||
|
config.MoreSettings = new ConnMoreSettings |
||||
|
{ |
||||
|
IsAutoRemoveDataCache = true |
||||
|
}; |
||||
|
}); |
||||
|
|
||||
|
SqlSugarScope sqlSugar = new(dbOptions.ConnectionConfigs.Adapt<List<ConnectionConfig>>(), client => |
||||
|
{ |
||||
|
dbOptions.ConnectionConfigs.ForEach(config => |
||||
|
{ |
||||
|
var db = client.GetConnectionScope((string)config.ConfigId); |
||||
|
|
||||
|
// 设置超时时间
|
||||
|
db.Ado.CommandTimeOut = 30; |
||||
|
|
||||
|
// 打印SQL语句
|
||||
|
db.Aop.OnLogExecuting = (sql, pars) => |
||||
|
{ |
||||
|
if (sql.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase)) |
||||
|
Console.ForegroundColor = ConsoleColor.Green; |
||||
|
if (sql.StartsWith("UPDATE", StringComparison.OrdinalIgnoreCase) || sql.StartsWith("INSERT", StringComparison.OrdinalIgnoreCase)) |
||||
|
Console.ForegroundColor = ConsoleColor.White; |
||||
|
if (sql.StartsWith("DELETE", StringComparison.OrdinalIgnoreCase)) |
||||
|
Console.ForegroundColor = ConsoleColor.Blue; |
||||
|
Console.WriteLine("【" + DateTime.Now + "——执行SQL】\r\n" + UtilMethods.GetSqlString(config.DbType, sql, pars) + "\r\n"); |
||||
|
App.PrintToMiniProfiler("SqlSugar", "Info", sql + "\r\n" + db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value))); |
||||
|
}; |
||||
|
db.Aop.OnError = (ex) => |
||||
|
{ |
||||
|
Console.ForegroundColor = ConsoleColor.Red; |
||||
|
var pars = db.Utilities.SerializeObject(((SugarParameter[])ex.Parametres).ToDictionary(it => it.ParameterName, it => it.Value)); |
||||
|
Console.WriteLine("【" + DateTime.Now + "——错误SQL】\r\n" + UtilMethods.GetSqlString(config.DbType, ex.Sql, (SugarParameter[])ex.Parametres) + "\r\n"); |
||||
|
App.PrintToMiniProfiler("SqlSugar", "Error", $"{ex.Message}{Environment.NewLine}{ex.Sql}{pars}{Environment.NewLine}"); |
||||
|
}; |
||||
|
|
||||
|
// 数据审计
|
||||
|
db.Aop.DataExecuting = (oldValue, entityInfo) => |
||||
|
{ |
||||
|
// 新增操作
|
||||
|
if (entityInfo.OperationType == DataFilterType.InsertByObject) |
||||
|
{ |
||||
|
// 主键(long类型)且没有值的---赋值雪花Id
|
||||
|
if (entityInfo.EntityColumnInfo.IsPrimarykey && entityInfo.EntityColumnInfo.PropertyInfo.PropertyType == typeof(long)) |
||||
|
{ |
||||
|
var id = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue); |
||||
|
if (id == null || (long)id == 0) |
||||
|
entityInfo.SetValue(Yitter.IdGenerator.YitIdHelper.NextId()); |
||||
|
} |
||||
|
if (entityInfo.PropertyName == "CreateTime") |
||||
|
entityInfo.SetValue(DateTime.Now); |
||||
|
} |
||||
|
// 更新操作
|
||||
|
if (entityInfo.OperationType == DataFilterType.UpdateByObject) |
||||
|
{ |
||||
|
if (entityInfo.PropertyName == "UpdateTime") |
||||
|
entityInfo.SetValue(DateTime.Now); |
||||
|
} |
||||
|
}; |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
// 初始化数据库表结构及种子数据
|
||||
|
InitDataBase(sqlSugar, dbOptions); |
||||
|
|
||||
|
services.AddSingleton<ISqlSugarClient>(sqlSugar); // 单例注册
|
||||
|
services.AddScoped(typeof(SqlSugarRepository<>)); // 注册仓储
|
||||
|
services.AddUnitOfWork<SqlSugarUnitOfWork>(); // 注册事务与工作单元
|
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 初始化数据库结构
|
||||
|
/// </summary>
|
||||
|
private static void InitDataBase(SqlSugarScope db, DbConnectionOptions dbOptions) |
||||
|
{ |
||||
|
// 创建数据库
|
||||
|
dbOptions.ConnectionConfigs.ForEach(config => |
||||
|
{ |
||||
|
if (!config.EnableInitDb || config.DbType == SqlSugar.DbType.Oracle) return; |
||||
|
db.GetConnectionScope(config.ConfigId).DbMaintenance.CreateDatabase(); |
||||
|
}); |
||||
|
|
||||
|
// 获取所有实体表-初始化表结构
|
||||
|
var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass |
||||
|
&& u.IsDefined(typeof(SugarTable), false) && !u.IsDefined(typeof(NotTableAttribute), false)); |
||||
|
if (!entityTypes.Any()) return; |
||||
|
foreach (var entityType in entityTypes) |
||||
|
{ |
||||
|
var tAtt = entityType.GetCustomAttribute<TenantAttribute>(); // 多数据库
|
||||
|
var configId = tAtt == null ? SqlSugarConst.DefaultConfigId : tAtt.configId.ToString(); |
||||
|
if (!dbOptions.ConnectionConfigs.FirstOrDefault(u => u.ConfigId == configId).EnableInitDb) |
||||
|
continue; |
||||
|
var db2 = db.GetConnectionScope(configId); |
||||
|
var splitTable = entityType.GetCustomAttribute<SplitTableAttribute>(); // 分表
|
||||
|
if (splitTable == null) |
||||
|
db2.CodeFirst.InitTables(entityType); |
||||
|
else |
||||
|
db2.CodeFirst.SplitTables().InitTables(entityType); |
||||
|
} |
||||
|
|
||||
|
// 获取所有种子配置-初始化数据
|
||||
|
var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass |
||||
|
&& u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>)))); |
||||
|
if (!seedDataTypes.Any()) return; |
||||
|
foreach (var seedType in seedDataTypes) |
||||
|
{ |
||||
|
var instance = Activator.CreateInstance(seedType); |
||||
|
|
||||
|
var hasDataMethod = seedType.GetMethod("HasData"); |
||||
|
var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast<object>(); |
||||
|
if (seedData == null) continue; |
||||
|
|
||||
|
var entityType = seedType.GetInterfaces().First().GetGenericArguments().First(); |
||||
|
var tAtt = entityType.GetCustomAttribute<TenantAttribute>(); |
||||
|
var configId = tAtt == null ? SqlSugarConst.DefaultConfigId : tAtt.configId.ToString(); |
||||
|
if (!dbOptions.ConnectionConfigs.FirstOrDefault(u => u.ConfigId == configId).EnableInitDb) |
||||
|
continue; |
||||
|
var db2 = db.GetConnectionScope(configId); |
||||
|
var seedDataTable = seedData.ToList().ToDataTable(); |
||||
|
seedDataTable.TableName = db.EntityMaintenance.GetEntityInfo(entityType).DbTableName; |
||||
|
if (seedDataTable.Columns.Contains(SqlSugarConst.DefaultPrimaryKey)) |
||||
|
{ |
||||
|
var storage = db2.Storageable(seedDataTable).WhereColumns(SqlSugarConst.DefaultPrimaryKey).ToStorage(); |
||||
|
storage.AsInsertable.ExecuteCommand(); |
||||
|
storage.AsUpdateable.ExecuteCommand(); |
||||
|
} |
||||
|
else // 没有主键或者不是预定义的主键(没主键有重复的可能)
|
||||
|
{ |
||||
|
var storage = db2.Storageable(seedDataTable).ToStorage(); |
||||
|
storage.AsInsertable.ExecuteCommand(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,65 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// SqlSugar 事务和工作单元
|
||||
|
/// </summary>
|
||||
|
public sealed class SqlSugarUnitOfWork : IUnitOfWork |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// SqlSugar 对象
|
||||
|
/// </summary>
|
||||
|
private readonly ISqlSugarClient _sqlSugarClient; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 构造函数
|
||||
|
/// </summary>
|
||||
|
/// <param name="sqlSugarClient"></param>
|
||||
|
public SqlSugarUnitOfWork(ISqlSugarClient sqlSugarClient) |
||||
|
{ |
||||
|
_sqlSugarClient = sqlSugarClient; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 开启工作单元处理
|
||||
|
/// </summary>
|
||||
|
/// <param name="context"></param>
|
||||
|
/// <param name="unitOfWork"></param>
|
||||
|
/// <exception cref="NotImplementedException"></exception>
|
||||
|
public void BeginTransaction(FilterContext context, UnitOfWorkAttribute unitOfWork) |
||||
|
{ |
||||
|
_sqlSugarClient.AsTenant().BeginTran(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 提交工作单元处理
|
||||
|
/// </summary>
|
||||
|
/// <param name="resultContext"></param>
|
||||
|
/// <param name="unitOfWork"></param>
|
||||
|
/// <exception cref="NotImplementedException"></exception>
|
||||
|
public void CommitTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork) |
||||
|
{ |
||||
|
_sqlSugarClient.AsTenant().CommitTran(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 回滚工作单元处理
|
||||
|
/// </summary>
|
||||
|
/// <param name="resultContext"></param>
|
||||
|
/// <param name="unitOfWork"></param>
|
||||
|
/// <exception cref="NotImplementedException"></exception>
|
||||
|
public void RollbackTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork) |
||||
|
{ |
||||
|
_sqlSugarClient.AsTenant().RollbackTran(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 执行完毕(无论成功失败)
|
||||
|
/// </summary>
|
||||
|
/// <param name="context"></param>
|
||||
|
/// <param name="resultContext"></param>
|
||||
|
/// <exception cref="NotImplementedException"></exception>
|
||||
|
public void OnCompleted(FilterContext context, FilterContext resultContext) |
||||
|
{ |
||||
|
_sqlSugarClient.Dispose(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,128 @@ |
|||||
|
namespace Cis.Core; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 全局规范化结果
|
||||
|
/// </summary>
|
||||
|
[UnifyModel(typeof(RespParam<>))] |
||||
|
public class RespParamProvider : IUnifyResultProvider |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 异常返回值
|
||||
|
/// </summary>
|
||||
|
/// <param name="context"></param>
|
||||
|
/// <param name="metadata"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata) |
||||
|
{ |
||||
|
return new JsonResult(RESTfulResult(metadata.StatusCode, data: metadata.Data, errors: metadata.Errors)); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 成功返回值
|
||||
|
/// </summary>
|
||||
|
/// <param name="context"></param>
|
||||
|
/// <param name="data"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public IActionResult OnSucceeded(ActionExecutedContext context, object data) |
||||
|
{ |
||||
|
return new JsonResult(RESTfulResult(StatusCodes.Status200OK, true, data)); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 验证失败返回值
|
||||
|
/// </summary>
|
||||
|
/// <param name="context"></param>
|
||||
|
/// <param name="metadata"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata) |
||||
|
{ |
||||
|
return new JsonResult(RESTfulResult(metadata.StatusCode ?? StatusCodes.Status400BadRequest, data: metadata.Data, errors: metadata.ValidationResult)); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 特定状态码返回值
|
||||
|
/// </summary>
|
||||
|
/// <param name="context"></param>
|
||||
|
/// <param name="statusCode"></param>
|
||||
|
/// <param name="unifyResultSettings"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public async Task OnResponseStatusCodes(HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings) |
||||
|
{ |
||||
|
// 设置响应状态码
|
||||
|
UnifyContext.SetResponseStatusCodes(context, statusCode, unifyResultSettings); |
||||
|
|
||||
|
switch (statusCode) |
||||
|
{ |
||||
|
// 处理 401 状态码
|
||||
|
case StatusCodes.Status401Unauthorized: |
||||
|
await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "401 登录已过期,请重新登录"), |
||||
|
App.GetOptions<JsonOptions>()?.JsonSerializerOptions); |
||||
|
break; |
||||
|
// 处理 403 状态码
|
||||
|
case StatusCodes.Status403Forbidden: |
||||
|
await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "403 禁止访问,没有权限"), |
||||
|
App.GetOptions<JsonOptions>()?.JsonSerializerOptions); |
||||
|
break; |
||||
|
|
||||
|
default: break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 返回 RESTful 风格结果集
|
||||
|
/// </summary>
|
||||
|
/// <param name="statusCode"></param>
|
||||
|
/// <param name="succeeded"></param>
|
||||
|
/// <param name="data"></param>
|
||||
|
/// <param name="errors"></param>
|
||||
|
/// <returns></returns>
|
||||
|
private static RespParam<object> RESTfulResult(int statusCode, bool succeeded = default, object data = default, object errors = default) |
||||
|
{ |
||||
|
return new RespParam<object> |
||||
|
{ |
||||
|
Code = statusCode, |
||||
|
Message = errors is string str ? str : JSON.Serialize(errors), |
||||
|
Data = data, |
||||
|
Type = succeeded ? "success" : "error", |
||||
|
Extras = UnifyContext.Take(), |
||||
|
Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 全局返回结果
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T"></typeparam>
|
||||
|
public class RespParam<T> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 状态码
|
||||
|
/// </summary>
|
||||
|
public int Code { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 类型success、warning、error
|
||||
|
/// </summary>
|
||||
|
public string Type { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 错误信息
|
||||
|
/// </summary>
|
||||
|
public string Message { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 数据
|
||||
|
/// </summary>
|
||||
|
public T Data { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 附加数据
|
||||
|
/// </summary>
|
||||
|
public object Extras { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 时间戳
|
||||
|
/// </summary>
|
||||
|
public long Timestamp { get; set; } |
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
using Cis.Core; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
|
||||
|
namespace Cis.Web.Core; |
||||
|
|
||||
|
public static class ProjectOptions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 注册项目配置选项
|
||||
|
/// </summary>
|
||||
|
/// <param name="services"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public static IServiceCollection AddProjectOptions(this IServiceCollection services) |
||||
|
{ |
||||
|
services.AddConfigurableOptions<DbConnectionOptions>(); |
||||
|
services.AddConfigurableOptions<CacheOptions>(); |
||||
|
services.AddConfigurableOptions<SnowIdOptions>(); |
||||
|
|
||||
|
return services; |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue