Browse Source

fix: 修改框架

master
fajiao 2 years ago
parent
commit
e11ae02208
  1. 4
      Cis.Application/AppConfig.json
  2. 44
      Cis.Application/Cb/Common/CbInfo.cs
  3. 44
      Cis.Application/Cb/Entity/CbCamera.cs
  4. 56
      Cis.Application/Cb/Service/CbCameraService.cs
  5. 44
      Cis.Application/Cm/Common/CmInfo.cs
  6. 28
      Cis.Application/Cm/Entity/CmMarkGroup.cs
  7. 15
      Cis.Application/Cm/Service/CmMarkGroupService.cs
  8. 26
      Cis.Application/Startup.cs
  9. 54
      Cis.Application/Sys/Common/SysInfo.cs
  10. 54
      Cis.Application/Sys/Entity/SysDictData.cs
  11. 41
      Cis.Application/Sys/Entity/SysDictType.cs
  12. 16
      Cis.Application/Sys/Service/SysDictDataService.cs
  13. 15
      Cis.Application/Sys/Service/SysDictTypeService.cs
  14. 10
      Cis.Core/Attribute/NotTableAttribute.cs
  15. 28
      Cis.Core/Cache/CacheSetup.cs
  16. 51
      Cis.Core/Cache/SqlSugarCache.cs
  17. 14
      Cis.Core/Const/SqlSugarConst.cs
  18. 46
      Cis.Core/CoreConfig.json
  19. 61
      Cis.Core/Entity/EntityBase.cs
  20. 47
      Cis.Core/Entity/Pagination.cs
  21. 19
      Cis.Core/Enum/CacheTypeEnum.cs
  22. 19
      Cis.Core/Enum/StatusEnum.cs
  23. 141
      Cis.Core/Extension/ObjectExtension.cs
  24. 23
      Cis.Core/GlobalUsing.cs
  25. 17
      Cis.Core/Option/CacheOptions.cs
  26. 20
      Cis.Core/Option/DbConnectionOptions.cs
  27. 12
      Cis.Core/Option/SnowIdOptions.cs
  28. 13
      Cis.Core/SqlSugar/IEntityFilter.cs
  29. 15
      Cis.Core/SqlSugar/ISqlSugarEntitySeedData.cs
  30. 100
      Cis.Core/SqlSugar/SqlSugarPagedList.cs
  31. 16
      Cis.Core/SqlSugar/SqlSugarRepository.cs
  32. 159
      Cis.Core/SqlSugar/SqlSugarSetup.cs
  33. 65
      Cis.Core/SqlSugar/SqlSugarUnitOfWork.cs
  34. 128
      Cis.Core/Util/RespParamProvider.cs
  35. 21
      Cis.Web.Core/ProjectOptions.cs

4
Cis.Application/AppConfig.json

@ -0,0 +1,4 @@
{
"$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
}

44
Cis.Application/Cb/Common/CbInfo.cs

@ -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
}

44
Cis.Application/Cb/Entity/CbCamera.cs

@ -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; }
}

56
Cis.Application/Cb/Service/CbCameraService.cs

@ -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);
}
}

44
Cis.Application/Cm/Common/CmInfo.cs

@ -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
}

28
Cis.Application/Cm/Entity/CmMarkGroup.cs

@ -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; }
}

15
Cis.Application/Cm/Service/CmMarkGroupService.cs

@ -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;
}
}

26
Cis.Application/Startup.cs

@ -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)
{
}
}

54
Cis.Application/Sys/Common/SysInfo.cs

@ -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
}

54
Cis.Application/Sys/Entity/SysDictData.cs

@ -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;
}

41
Cis.Application/Sys/Entity/SysDictType.cs

@ -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;
}

16
Cis.Application/Sys/Service/SysDictDataService.cs

@ -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;
}
}

15
Cis.Application/Sys/Service/SysDictTypeService.cs

@ -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;
}
}

10
Cis.Core/Attribute/NotTableAttribute.cs

@ -0,0 +1,10 @@
namespace Cis.Core;
/// <summary>
/// 非实体表特性
/// </summary>
[SuppressSniffer]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class NotTableAttribute : Attribute
{
}

28
Cis.Core/Cache/CacheSetup.cs

@ -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;
}
});
}
}

51
Cis.Core/Cache/SqlSugarCache.cs

@ -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);
}
}

14
Cis.Core/Const/SqlSugarConst.cs

@ -0,0 +1,14 @@
namespace Cis.Core;
public class SqlSugarConst
{
/// <summary>
/// 默认数据库标识
/// </summary>
public const string DefaultConfigId = "Cis";
/// <summary>
/// 默认表主键
/// </summary>
public const string DefaultPrimaryKey = "Id";
}

46
Cis.Core/CoreConfig.json

@ -0,0 +1,46 @@
{
"$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
"DbConnection": {
"ConnectionConfigs": [
{
"ConfigId": "Cis",
"DbType": "MySql", // MySqlSqlServerSqliteOraclePostgreSQLDmKdbndpOscarMySqlConnectorAccess
"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", // MemoryRedis
"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"
]
}
}

61
Cis.Core/Entity/EntityBase.cs

@ -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; }
}

47
Cis.Core/Entity/Pagination.cs

@ -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;
}
}
}
}

19
Cis.Core/Enum/CacheTypeEnum.cs

@ -0,0 +1,19 @@
namespace Cis.Core;
/// <summary>
/// 缓存类型枚举
/// </summary>
public enum CacheTypeEnum
{
/// <summary>
/// 内存缓存
/// </summary>
[Description("内存缓存")]
Memory,
/// <summary>
/// Redis缓存
/// </summary>
[Description("Redis缓存")]
Redis
}

19
Cis.Core/Enum/StatusEnum.cs

@ -0,0 +1,19 @@
namespace Cis.Core;
/// <summary>
/// 通用状态枚举
/// </summary>
public enum StatusEnum
{
/// <summary>
/// 停用
/// </summary>
[Description("停用")]
Disable = 0,
/// <summary>
/// 启用
/// </summary>
[Description("启用")]
Enable = 1,
}

141
Cis.Core/Extension/ObjectExtension.cs

@ -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("&nbsp;", ""));
}
/// <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;
}
}

23
Cis.Core/GlobalUsing.cs

@ -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;

17
Cis.Core/Option/CacheOptions.cs

@ -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; }
}

20
Cis.Core/Option/DbConnectionOptions.cs

@ -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; }
}

12
Cis.Core/Option/SnowIdOptions.cs

@ -0,0 +1,12 @@
namespace Cis.Core;
/// <summary>
/// 雪花Id配置选项
/// </summary>
public sealed class SnowIdOptions : IConfigurableOptions
{
/// <summary>
/// 机器码
/// </summary>
public ushort WorkerId { get; set; }
}

13
Cis.Core/SqlSugar/IEntityFilter.cs

@ -0,0 +1,13 @@
namespace Cis.Core;
/// <summary>
/// 自定义实体过滤器接口
/// </summary>
public interface IEntityFilter
{
/// <summary>
/// 实体过滤器
/// </summary>
/// <returns></returns>
IEnumerable<TableFilterItem<object>> AddEntityFilter();
}

15
Cis.Core/SqlSugar/ISqlSugarEntitySeedData.cs

@ -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();
}

100
Cis.Core/SqlSugar/SqlSugarPagedList.cs

@ -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
};
}
}

16
Cis.Core/SqlSugar/SqlSugarRepository.cs

@ -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>();
}
}

159
Cis.Core/SqlSugar/SqlSugarSetup.cs

@ -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();
}
}
}
}

65
Cis.Core/SqlSugar/SqlSugarUnitOfWork.cs

@ -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();
}
}

128
Cis.Core/Util/RespParamProvider.cs

@ -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; }
}

21
Cis.Web.Core/ProjectOptions.cs

@ -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…
Cancel
Save