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