diff --git a/Cis.Application/Cb/Common/CbInfo.cs b/Cis.Application/Cb/Common/CbInfo.cs index f64368f..b612a81 100644 --- a/Cis.Application/Cb/Common/CbInfo.cs +++ b/Cis.Application/Cb/Common/CbInfo.cs @@ -22,7 +22,7 @@ public class CbInfo #region Database Info /// - /// 数据库名 + /// 数据库标识 /// public const string DbName = SqlSugarConst.DefaultConfigId; diff --git a/Cis.Application/Cb/Service/CbCameraService.cs b/Cis.Application/Cb/Service/CbCameraService.cs index 165cffb..156e370 100644 --- a/Cis.Application/Cb/Service/CbCameraService.cs +++ b/Cis.Application/Cb/Service/CbCameraService.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json.Linq; -using System.Runtime.InteropServices; namespace Cis.Application.Cb; @@ -22,7 +21,7 @@ public class CbCameraService : IDynamicApiController, ITransient return entity; } - public async Task> GetList(string queryJson) + public async Task> GetList(string queryJson = "") { JObject queryObj = queryJson.ToJObject(); List list = await _cbCameraRep.AsQueryable() diff --git a/Cis.Application/Cis.Application.xml b/Cis.Application/Cis.Application.xml index 4107b98..45840b3 100644 --- a/Cis.Application/Cis.Application.xml +++ b/Cis.Application/Cis.Application.xml @@ -21,7 +21,7 @@ - 数据库名 + 数据库标识 @@ -86,7 +86,7 @@ - 数据库名 + 数据库标识 @@ -99,6 +99,16 @@ CmMarkGroup 表描述 + + + CmMarkLabel 表名 + + + + + CmMarkLabel 表描述 + + 标记分组表 @@ -119,11 +129,106 @@ 备注 + + + 标记标签表 + + + + + 名称 + + + + + Pan 位置 + + + + + Tilt 位置 + + + + + Zoom 位置 + + + + + 备注 + + + + + 相机 Id + + + + + 标记组 Id + + 标记分组服务 + + + 标记标签服务 + + + + + Ptz 信息 + + + + + Pan + + + + + Tilt + + + + + Zoom + + + + + Ptz Api 接口 + + + + + Ptz Api + + + + + PtzServer选项 + + + + + 服务类别 + + + + + 服务IP + + + + + 服务端口 + + 配置应用所需服务,在该方法中可以添加应用所需要的功能或服务 @@ -154,7 +259,7 @@ - 数据库名 + 数据库标识 @@ -257,5 +362,15 @@ 系统字典类型服务 + + + 数据库标识 + + + + + TbPtzCamera 表名 + + diff --git a/Cis.Application/Cm/Common/CmInfo.cs b/Cis.Application/Cm/Common/CmInfo.cs index f82d8e1..abfda16 100644 --- a/Cis.Application/Cm/Common/CmInfo.cs +++ b/Cis.Application/Cm/Common/CmInfo.cs @@ -22,7 +22,7 @@ public class CmInfo #region Database Info /// - /// 数据库名 + /// 数据库标识 /// public const string DbName = SqlSugarConst.DefaultConfigId; @@ -40,5 +40,15 @@ public class CmInfo /// public const string CmMarkGroupTbDesc = "标记分组表"; + /// + /// CmMarkLabel 表名 + /// + public const string CmMarkLabelTbName = "cm_mark_label"; + + /// + /// CmMarkLabel 表描述 + /// + public const string CmMarkLabelTbDesc = "标记标签表"; + #endregion Table Info } \ No newline at end of file diff --git a/Cis.Application/Cm/Entity/CmMarkLabel.cs b/Cis.Application/Cm/Entity/CmMarkLabel.cs new file mode 100644 index 0000000..bb0429a --- /dev/null +++ b/Cis.Application/Cm/Entity/CmMarkLabel.cs @@ -0,0 +1,52 @@ +namespace Cis.Application.Cm; + +/// +/// 标记标签表 +/// +[SugarTable(CmInfo.CmMarkLabelTbName, CmInfo.CmMarkLabelTbDesc)] +[Tenant(CmInfo.DbName)] +public class CmMarkLabel : EntityBase +{ + /// + /// 名称 + /// + [SugarColumn(ColumnDescription = "名称", Length = 64)] + public string Name { get; set; } + + /// + /// Pan 位置 + /// + [SugarColumn(ColumnDescription = "Pan位置")] + public double PanPosition { get; set; } + + /// + /// Tilt 位置 + /// + [SugarColumn(ColumnDescription = "Tilt位置")] + public double TiltPosition { get; set; } + + /// + /// Zoom 位置 + /// + [SugarColumn(ColumnDescription = "Zoom位置")] + public double ZoomPosition { get; set; } + + /// + /// 备注 + /// + [SugarColumn(ColumnDescription = "备注", Length = 256)] + [MaxLength(256)] + public string Remark { get; set; } + + /// + /// 相机 Id + /// + [SugarColumn(ColumnDescription = "相机Id")] + public long CbCameraId { get; set; } + + /// + /// 标记组 Id + /// + [SugarColumn(ColumnDescription = "标记组Id")] + public long CmMarkGroupId { get; set; } +} \ No newline at end of file diff --git a/Cis.Application/Cm/Service/CmMarkGroupService.cs b/Cis.Application/Cm/Service/CmMarkGroupService.cs index faabdb0..2cf1302 100644 --- a/Cis.Application/Cm/Service/CmMarkGroupService.cs +++ b/Cis.Application/Cm/Service/CmMarkGroupService.cs @@ -1,4 +1,6 @@ -namespace Cis.Application.Cm; +using Newtonsoft.Json.Linq; + +namespace Cis.Application.Cm; /// /// 标记分组服务 @@ -12,4 +14,42 @@ public class CmMarkGroupService : IDynamicApiController, ITransient { _cmMarkGroupRep = cmMarkGroupRep; } + + public async Task Get(long id) + { + CmMarkGroup entity = await _cmMarkGroupRep.GetByIdAsync(id); + return entity; + } + + public async Task> GetList(string queryJson) + { + JObject queryObj = queryJson.ToJObject(); + List list = await _cmMarkGroupRep.AsQueryable() + .ToListAsync(); + return list; + } + + public async Task> GetPageList(string queryJson, string pagination) + { + Pagination pageObj = pagination.ToObject(); + JObject queryObj = queryJson.ToJObject(); + List list = await _cmMarkGroupRep.AsQueryable() + .ToPageListAsync(pageObj.Index, pageObj.Size); + return list; + } + + public async Task Add(CmMarkGroup entity) + { + await _cmMarkGroupRep.InsertAsync(entity); + } + + public async Task Update(CmMarkGroup entity) + { + await _cmMarkGroupRep.UpdateAsync(entity); + } + + public async Task Delete(CmMarkGroup entity) + { + await _cmMarkGroupRep.DeleteAsync(entity); + } } \ No newline at end of file diff --git a/Cis.Application/Cm/Service/CmMarkLabelService.cs b/Cis.Application/Cm/Service/CmMarkLabelService.cs new file mode 100644 index 0000000..3df7e79 --- /dev/null +++ b/Cis.Application/Cm/Service/CmMarkLabelService.cs @@ -0,0 +1,55 @@ +using Newtonsoft.Json.Linq; + +namespace Cis.Application.Cm; + +/// +/// 标记标签服务 +/// +[ApiDescriptionSettings(CmInfo.GroupName, Order = CmInfo.GroupOrder)] +public class CmMarkLabelService : IDynamicApiController, ITransient +{ + private readonly SqlSugarRepository _cmMarkLabelRep; + + public CmMarkLabelService(SqlSugarRepository cmMarkLabelRep) + { + _cmMarkLabelRep = cmMarkLabelRep; + } + + public async Task Get(long id) + { + CmMarkLabel entity = await _cmMarkLabelRep.GetByIdAsync(id); + return entity; + } + + public async Task> GetList(string queryJson = "") + { + JObject queryObj = queryJson.ToJObject(); + List list = await _cmMarkLabelRep.AsQueryable() + .ToListAsync(); + return list; + } + + public async Task> GetPageList(string queryJson, string pagination) + { + Pagination pageObj = pagination.ToObject(); + JObject queryObj = queryJson.ToJObject(); + List list = await _cmMarkLabelRep.AsQueryable() + .ToPageListAsync(pageObj.Index, pageObj.Size); + return list; + } + + public async Task Add(CmMarkLabel entity) + { + await _cmMarkLabelRep.InsertAsync(entity); + } + + public async Task Update(CmMarkLabel entity) + { + await _cmMarkLabelRep.UpdateAsync(entity); + } + + public async Task Delete(CmMarkLabel entity) + { + await _cmMarkLabelRep.DeleteAsync(entity); + } +} \ No newline at end of file diff --git a/Cis.Application/Core/Algo/MarkSearcherBase.cs b/Cis.Application/Core/Algo/MarkSearcherBase.cs new file mode 100644 index 0000000..033a34b --- /dev/null +++ b/Cis.Application/Core/Algo/MarkSearcherBase.cs @@ -0,0 +1,6 @@ +namespace Cis.Application.Core; + +public class MarkSearcherBase +{ + +} \ No newline at end of file diff --git a/Cis.Application/Core/Api/IPtzApi.cs b/Cis.Application/Core/Api/IPtzApi.cs new file mode 100644 index 0000000..e3461e5 --- /dev/null +++ b/Cis.Application/Core/Api/IPtzApi.cs @@ -0,0 +1,9 @@ +namespace Cis.Application.Core; + +/// +/// Ptz Api 接口 +/// +public interface IPtzApi +{ + +} \ No newline at end of file diff --git a/Cis.Application/Core/Api/PtzServerApi.cs b/Cis.Application/Core/Api/PtzServerApi.cs new file mode 100644 index 0000000..4f65872 --- /dev/null +++ b/Cis.Application/Core/Api/PtzServerApi.cs @@ -0,0 +1,198 @@ +using System.Net.Sockets; +using System.Runtime.InteropServices; + +namespace Cis.Application.Core; + +/// +/// Ptz Api +/// +public class PtzServerApi : IPtzApi, ISingleton +{ + #region Attr + + private TcpClient _tcpClient { get; set; } + + private NetworkStream _stream { get; set; } + + #endregion Attr + + public PtzServerApi() + { + PtzServerOptions options = App.GetOptions(); + _tcpClient = new TcpClient(options.Ip, options.Port); + //创建一个 networkstream 用来写入和读取数据 + _stream = _tcpClient.GetStream(); + } + + public RequestRealControl GetPtzInfo(int cameraId) + { + RequestRealControl realControl = new(); + try + { + string recieve_string = string.Empty; + realControl.token = 666; + + realControl.CameraInfo.cameraid = cameraId; + realControl.Status = true; + realControl.realControlType = RealControlType.PTZINFO_GET_; + byte[] data = StructToByte(realControl); + _stream.Write(data, 0, data.Length); + + byte[] recieve_byte = new byte[_tcpClient.ReceiveBufferSize]; + _stream.Read(recieve_byte, 0, (int)_tcpClient.ReceiveBufferSize); + //stream.BeginRead(recieve_byte, 0, (int)tcp_client.ReceiveBufferSize,EndRead, stream); + realControl = (RequestRealControl)BytetoStruct(recieve_byte, typeof(RequestRealControl)); + if (realControl.PTZPositionInfo.FT < 0) + { + realControl.PTZPositionInfo.FT = 3600 + realControl.PTZPositionInfo.FT; + } + } + catch (Exception) + { + realControl = default; + } + return realControl; + } + + public static byte[] StructToByte(object structObj) + { + //获取结构体大小 + int size = Marshal.SizeOf(structObj); + + byte[] data = new byte[size]; + + //分配内存空间 + IntPtr structPtr = Marshal.AllocHGlobal(size); + // 将结构体数据复制到内存空间 + Marshal.StructureToPtr(structObj, structPtr, false); + // 将内存空间的数据拷贝到byte数组 + Marshal.Copy(structPtr, data, 0, size); + //释放内存 + Marshal.FreeHGlobal(structPtr); + return data; + } + + public static object BytetoStruct(byte[] bytes, Type type) + { + object obj = new object(); + try + { + byte[] temp = bytes; + // 获取结构体大小 + int size = Marshal.SizeOf(type); + if (size > bytes.Length) + return null; + // 分配结构体内存空间 + IntPtr structPtr = Marshal.AllocHGlobal(size); + // 将byte数组内容拷贝到内存中 + Marshal.Copy(temp, 0, structPtr, size); + + // 将内存空间转化为目标结构体 + obj = Marshal.PtrToStructure(structPtr, type); + //释放内存 + Marshal.FreeHGlobal(structPtr); + } + catch (Exception) + { + } + return obj; + } + +} + +#region 与ptz服务交互使用结构体 + +//---------------------------------------------------------------------------------------- +// 与ptz服务交互使用结构体 +//---------------------------------------------------------------------------------------- +//注意这个属性不能少 +[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] +public struct RequestRealControl +{ + public int token; + + public CameraInfo CameraInfo; + + public RealControlType realControlType; + + //请求时 状态 true:开始;false:结束 答复时:true:成功;其他:失败 + public bool Status; + + public PresentInfo PresentInfo; + + public PTZPosInfo PTZPositionInfo; + //int数组,SizeConst表示数组的个数,在转换成 + //byte数组前必须先初始化数组,再使用,初始化 + //的数组长度必须和SizeConst一致,例test = new int[6]; + //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + //public int[] test; +} + +[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)] +public struct CameraInfo +{ + public int cameraid; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] + public char[] ip; + + public ushort port; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] + private char[] user; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] + private char[] password; +} + +[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)] +public struct PresentInfo +{ + public int presentNo;//预置位编号 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] + private char[] PresentName; // 预置位名称 +} + +[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)] +public struct PTZPosInfo +{ + public int FP;//p信息 + public int FT;//T信息 + public int FZ;//Z信息 + public int TitlePosMin;//描述点垂直参数min + public int ZoomPosMin;//描述点变倍参数min + + public float FHorWidth;//水平宽度 精确到小数点后两位 *10000 + public float FVerWidth;//垂直宽度 精确到小数点后两位 *10000 + public float FFold;//zoom=1没变时的焦距 精确到小数点后两位 *100 + + public int CameraType; +} + +public enum RealControlType +{ + MOVE_UP_ = 1, + MOVE_DOWN_, + MOVE_LEFT_, + MOVE_RIGHT_, + MOVE_LEFTUP_, + MOVE_LEFTDOWN_, + MOVE_RIGHTUP_, + MOVE_RIGHTDOWN_, + + ZOOM_IN_, + ZOOM_OUT_, + FOCUS_NEAR_, + FOCUS_FAR_, + IRIS_OPEN_, + IRIS_CLOSE_, + + PRESET_SET_, + PRESET_CALL_, + + PTZINFO_GET_, + PTZINFO_SET_ +} + +#endregion 与ptz服务交互使用结构体 \ No newline at end of file diff --git a/Cis.Application/Core/Center/CameraDataCenter.cs b/Cis.Application/Core/Center/CameraDataCenter.cs new file mode 100644 index 0000000..5dc864b --- /dev/null +++ b/Cis.Application/Core/Center/CameraDataCenter.cs @@ -0,0 +1,113 @@ +using Cis.Application.Cb; +using Cis.Application.Cm; +using Cis.Application.Tb; +using System.Collections.Concurrent; + +namespace Cis.Application.Core; + +public class CameraDataCenter +{ + #region Attr + + private Thread _thread { get; set; } + private List _tbPtzCameraList { get; set; } + private ConcurrentDictionary _cameraPtzInfoDict { get; set; } + + private readonly SqlSugarRepository _cbCameraRep; + private readonly SqlSugarRepository _cmMarkLableRep; + private readonly SqlSugarRepository _tbPtzCameraRep; + private readonly PtzServerApi _ptzServerApi; + + #endregion Attr + + public CameraDataCenter() + { + _cbCameraRep = App.GetService>(); + _cmMarkLableRep = App.GetService>(); + _tbPtzCameraRep = App.GetService>(); + _ptzServerApi = App.GetService(); + Init(); + } + + private void Init() + { + // 初始化 tbPtzCameraList + _tbPtzCameraList = _tbPtzCameraRep.GetList(); + // 根据 Ip 去重 + _tbPtzCameraList = _tbPtzCameraList.Where((a, i) => _tbPtzCameraList.FindIndex(b => b.Ip == a.Ip) == i).ToList(); + + // 初始化 ptzInfoDict + _cameraPtzInfoDict = new ConcurrentDictionary(); + + // 初始化 thread + _thread = new Thread(WorkLoop) + { + IsBackground = true// 设置后台线程 + }; + _thread.Start(); + } + + private void LazyInit() + { + // 初始化 tbPtzCameraList + _tbPtzCameraList = new(); + + // 初始化 ptzInfoDict + _cameraPtzInfoDict = new ConcurrentDictionary(); + + // 初始化 thread + _thread = new Thread(WorkLoop) + { + IsBackground = true// 设置后台线程 + }; + _thread.Start(); + } + + #region Loop + + private void WorkLoop() + { + while (true) + { + GetPtzInfoByApi(); + Thread.Sleep(10000); + } + } + + private void GetPtzInfoByApi() + { + foreach (TbPtzCamera item in _tbPtzCameraList) + { + RequestRealControl rrc = _ptzServerApi.GetPtzInfo(item.CameraId); + CameraCalcInfo ptzInfo = new() + { + Pan = rrc.PTZPositionInfo.FP, + Tilt = rrc.PTZPositionInfo.FT, + Zoom = rrc.PTZPositionInfo.FZ + }; + _cameraPtzInfoDict[item.Ip] = ptzInfo; + } + } + + private void Calc() + { + } + + #endregion Loop + + #region external call + + public bool GetCamera(string ip) + { + return false; + } + + public bool ActiveCamera(string ip) + { + + + return false; + } + + #endregion external call +} \ No newline at end of file diff --git a/Cis.Application/Core/Common/Options.cs b/Cis.Application/Core/Common/Options.cs new file mode 100644 index 0000000..c121c2a --- /dev/null +++ b/Cis.Application/Core/Common/Options.cs @@ -0,0 +1,22 @@ +namespace Cis.Application.Core; + +/// +/// PtzServer选项 +/// +public class PtzServerOptions : IConfigurableOptions +{ + /// + /// 服务类别 + /// + public string Type { get; set; } + + /// + /// 服务IP + /// + public string Ip { get; set; } + + /// + /// 服务端口 + /// + public int Port { get; set; } +} \ No newline at end of file diff --git a/Cis.Application/Core/Entity/CameraCalcInfo.cs b/Cis.Application/Core/Entity/CameraCalcInfo.cs new file mode 100644 index 0000000..e34c9b6 --- /dev/null +++ b/Cis.Application/Core/Entity/CameraCalcInfo.cs @@ -0,0 +1,32 @@ +namespace Cis.Application.Core; + +/// +/// 相机 Ptz 信息 +/// +public class CameraCalcInfo +{ + /// + /// 图像的宽度 + /// + public int ImageWidth { get; set; } = 1920; + + /// + /// 图像的宽度 + /// + public int ImageHeight { get; set; } = 1080; + + /// + /// Pan + /// + public double Pan { get; set; } + + /// + /// Tilt + /// + public double Tilt { get; set; } + + /// + /// Zoom + /// + public double Zoom { get; set; } +} \ No newline at end of file diff --git a/Cis.Application/Core/Service/MarkSearchService.cs b/Cis.Application/Core/Service/MarkSearchService.cs new file mode 100644 index 0000000..0432a26 --- /dev/null +++ b/Cis.Application/Core/Service/MarkSearchService.cs @@ -0,0 +1,22 @@ +using Cis.Application.Cm; + +namespace Cis.Application.Core; + +[ApiDescriptionSettings(CmInfo.GroupName, Order = CmInfo.GroupOrder)] +public class MarkSearchService : IDynamicApiController, ITransient +{ + #region Attr + + private CameraDataCenter _cameraDataCenter { get; set; } + + #endregion Attr + + public MarkSearchService(CameraDataCenter cameraDataCenter) + { + _cameraDataCenter = cameraDataCenter; + } + + public void ActivateCamera() + { + } +} \ No newline at end of file diff --git a/Cis.Application/GlobalUsings.cs b/Cis.Application/GlobalUsings.cs index a7568c4..76b15eb 100644 --- a/Cis.Application/GlobalUsings.cs +++ b/Cis.Application/GlobalUsings.cs @@ -1,5 +1,6 @@ global using Cis.Core; global using Furion; +global using Furion.ConfigurableOptions; global using Furion.DependencyInjection; global using Furion.DynamicApiController; global using Microsoft.AspNetCore.Mvc; diff --git a/Cis.Application/Startup.cs b/Cis.Application/Startup.cs index d88de9c..19a7348 100644 --- a/Cis.Application/Startup.cs +++ b/Cis.Application/Startup.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Builder; +using Cis.Application.Core; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; @@ -12,8 +13,11 @@ public class Startup : AppStartup /// /// public void ConfigureServices(IServiceCollection services) - { - } + { + services.AddConfigurableOptions(); + + services.AddSingleton(new CameraDataCenter()); + } /// /// 配置应用请求处理管道 @@ -21,6 +25,6 @@ public class Startup : AppStartup /// /// public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - } + { + } } \ No newline at end of file diff --git a/Cis.Application/Sys/Common/SysInfo.cs b/Cis.Application/Sys/Common/SysInfo.cs index 3ffb68d..dbeea07 100644 --- a/Cis.Application/Sys/Common/SysInfo.cs +++ b/Cis.Application/Sys/Common/SysInfo.cs @@ -22,7 +22,7 @@ public class SysInfo #region Database Info /// - /// 数据库名 + /// 数据库标识 /// public const string DbName = SqlSugarConst.DefaultConfigId; diff --git a/Cis.Application/Sys/Service/SysDictDataService.cs b/Cis.Application/Sys/Service/SysDictDataService.cs index 0ac8c68..6042140 100644 --- a/Cis.Application/Sys/Service/SysDictDataService.cs +++ b/Cis.Application/Sys/Service/SysDictDataService.cs @@ -1,4 +1,6 @@ -namespace Cis.Application.Sys; +using Newtonsoft.Json.Linq; + +namespace Cis.Application.Sys; /// /// 系统字典值服务 @@ -13,4 +15,41 @@ public class SysDictDataService : IDynamicApiController, ITransient _sysDictDataRep = sysDictDataRep; } + public async Task Get(long id) + { + SysDictData entity = await _sysDictDataRep.GetByIdAsync(id); + return entity; + } + + public async Task> GetList(string queryJson) + { + JObject queryObj = queryJson.ToJObject(); + List list = await _sysDictDataRep.AsQueryable() + .ToListAsync(); + return list; + } + + public async Task> GetPageList(string queryJson, string pagination) + { + Pagination pageObj = pagination.ToObject(); + JObject queryObj = queryJson.ToJObject(); + List list = await _sysDictDataRep.AsQueryable() + .ToPageListAsync(pageObj.Index, pageObj.Size); + return list; + } + + public async Task Add(SysDictData entity) + { + await _sysDictDataRep.InsertAsync(entity); + } + + public async Task Update(SysDictData entity) + { + await _sysDictDataRep.UpdateAsync(entity); + } + + public async Task Delete(SysDictData entity) + { + await _sysDictDataRep.DeleteAsync(entity); + } } \ No newline at end of file diff --git a/Cis.Application/Sys/Service/SysDictTypeService.cs b/Cis.Application/Sys/Service/SysDictTypeService.cs index 74c1b17..4c9763b 100644 --- a/Cis.Application/Sys/Service/SysDictTypeService.cs +++ b/Cis.Application/Sys/Service/SysDictTypeService.cs @@ -1,4 +1,7 @@ -namespace Cis.Application.Sys; +using Cis.Application.Cm; +using Newtonsoft.Json.Linq; + +namespace Cis.Application.Sys; /// /// 系统字典类型服务 @@ -12,4 +15,42 @@ public class SysDictTypeService : IDynamicApiController, ITransient { _sysDictTypeRep = sysDictTypeRep; } + + public async Task Get(long id) + { + SysDictType entity = await _sysDictTypeRep.GetByIdAsync(id); + return entity; + } + + public async Task> GetList(string queryJson) + { + JObject queryObj = queryJson.ToJObject(); + List list = await _sysDictTypeRep.AsQueryable() + .ToListAsync(); + return list; + } + + public async Task> GetPageList(string queryJson, string pagination) + { + Pagination pageObj = pagination.ToObject(); + JObject queryObj = queryJson.ToJObject(); + List list = await _sysDictTypeRep.AsQueryable() + .ToPageListAsync(pageObj.Index, pageObj.Size); + return list; + } + + public async Task Add(SysDictType entity) + { + await _sysDictTypeRep.InsertAsync(entity); + } + + public async Task Update(SysDictType entity) + { + await _sysDictTypeRep.UpdateAsync(entity); + } + + public async Task Delete(SysDictType entity) + { + await _sysDictTypeRep.DeleteAsync(entity); + } } \ No newline at end of file diff --git a/Cis.Application/Tb/Common/TbInfo.cs b/Cis.Application/Tb/Common/TbInfo.cs new file mode 100644 index 0000000..135f94d --- /dev/null +++ b/Cis.Application/Tb/Common/TbInfo.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Cis.Application.Tb; + +public class TbInfo +{ + #region Database Info + + /// + /// 数据库标识 + /// + public const string DbName = "serverdb"; + + #endregion Database Info + + #region Table Info + + /// + /// TbPtzCamera 表名 + /// + public const string TbPtzCameraTbName = "tb_ptzcamera"; + + #endregion Table Info +} + diff --git a/Cis.Application/Tb/Entity/TbPtzCamera.cs b/Cis.Application/Tb/Entity/TbPtzCamera.cs new file mode 100644 index 0000000..6f75ea8 --- /dev/null +++ b/Cis.Application/Tb/Entity/TbPtzCamera.cs @@ -0,0 +1,28 @@ +namespace Cis.Application.Tb; + +[SugarTable(TbInfo.TbPtzCameraTbName)] +[Tenant(TbInfo.DbName)] +public class TbPtzCamera +{ + public int Id { get; set; } + + public int Type { get; set; } + + public string Ip { get; set; } + + public int Port { get; set; } + + public string User { get; set; } + + public string Pass { get; set; } + + public int CameraId { get; set; } + + public double PanPosition { get; set; } + + public double TitlePosition { get; set; } + + public double ZoomPosition { get; set; } + + public byte Request { get; set; } +} \ No newline at end of file diff --git a/Cis.Application/Tb/Service/TbPtzCameraService.cs b/Cis.Application/Tb/Service/TbPtzCameraService.cs new file mode 100644 index 0000000..03cb5bf --- /dev/null +++ b/Cis.Application/Tb/Service/TbPtzCameraService.cs @@ -0,0 +1,51 @@ +using Newtonsoft.Json.Linq; + +namespace Cis.Application.Tb; + +public class TbPtzCameraService : ITransient +{ + private readonly SqlSugarRepository _tbPtzCameraRep; + + public TbPtzCameraService(SqlSugarRepository tbPtzCameraRep) + { + _tbPtzCameraRep = tbPtzCameraRep; + } + + public async Task Get(int id) + { + TbPtzCamera entity = await _tbPtzCameraRep.GetByIdAsync(id); + return entity; + } + + public async Task> GetList(string queryJson = "") + { + JObject queryObj = !string.IsNullOrEmpty(queryJson) ? queryJson.ToJObject():default; + List list = await _tbPtzCameraRep.AsQueryable() + .ToListAsync(); + return list; + } + + public async Task> GetPageList(string pagination, string queryJson = "") + { + Pagination pageObj = pagination.ToObject(); + JObject queryObj = queryJson.ToJObject(); + List list = await _tbPtzCameraRep.AsQueryable() + .ToPageListAsync(pageObj.Index, pageObj.Size); + return list; + } + + public async Task Add(TbPtzCamera entity) + { + await _tbPtzCameraRep.InsertAsync(entity); + } + + public async Task Update(TbPtzCamera entity) + { + await _tbPtzCameraRep.UpdateAsync(entity); + } + + public async Task Delete(TbPtzCamera entity) + { + await _tbPtzCameraRep.DeleteAsync(entity); + } +} \ No newline at end of file diff --git a/Cis.Core/Cis.Core.csproj b/Cis.Core/Cis.Core.csproj index 6530dd8..27ffbae 100644 --- a/Cis.Core/Cis.Core.csproj +++ b/Cis.Core/Cis.Core.csproj @@ -22,11 +22,16 @@ + + + + + diff --git a/Cis.Core/Cis.Core.xml b/Cis.Core/Cis.Core.xml index 310f220..30c9dce 100644 --- a/Cis.Core/Cis.Core.xml +++ b/Cis.Core/Cis.Core.xml @@ -110,6 +110,90 @@ 页码数 + + + 全局规范化结果 + + + + + 异常返回值 + + + + + + + + 成功返回值 + + + + + + + + 验证失败返回值 + + + + + + + + 特定状态码返回值 + + + + + + + + + 返回 RESTful 风格结果集 + + + + + + + + + + 全局返回结果 + + + + + + 状态码 + + + + + 类型success、warning、error + + + + + 错误信息 + + + + + 数据 + + + + + 附加数据 + + + + + 时间戳 + + 缓存类型枚举 @@ -397,89 +481,5 @@ - - - 全局规范化结果 - - - - - 异常返回值 - - - - - - - - 成功返回值 - - - - - - - - 验证失败返回值 - - - - - - - - 特定状态码返回值 - - - - - - - - - 返回 RESTful 风格结果集 - - - - - - - - - - 全局返回结果 - - - - - - 状态码 - - - - - 类型success、warning、error - - - - - 错误信息 - - - - - 数据 - - - - - 附加数据 - - - - - 时间戳 - - diff --git a/Cis.Core/CoreConfig.json b/Cis.Core/CoreConfig.json index b6deb2e..471e3b9 100644 --- a/Cis.Core/CoreConfig.json +++ b/Cis.Core/CoreConfig.json @@ -10,7 +10,13 @@ //"ConnectionString": "DataSource=./cis.db", //"DbType": "PostgreSQL", //"ConnectionString": "HOST=127.0.0.1;PORT=5432;USER ID=pgsql;PASSWORD=123456;DATABASE=cis;", - "EnableInitDb": false, // 启用库表初始化 + "EnableInitDb": false // 启用库表初始化 + }, + { + "ConfigId": "serverdb", + "DbType": "MySql", + "ConnectionString": "Data Source=127.0.0.1;port=3306;User ID=root;Password=123456;Database=serverdb;pooling=true;sslmode=none;CharSet=utf8;", + "EnableInitDb": false // 启用库表初始化 } ] }, @@ -18,12 +24,17 @@ "CacheType": "Redis", // Memory、Redis "RedisConnectionString": "127.0.0.1:6379;password=123456;db=2" }, - "SnowId": { - "WorkerId": 5 // 取值范围0~63,默认1 + "PTZServer": { + "Type": "", + "Ip": "127.0.0.1", + "Port": "7022" + }, + "AppSettings": { + "InjectSpecificationDocument": true // 生产环境是否开启Swagger }, "SpecificationDocumentSettings": { - "DocumentTitle": "Swagger",//默认标题 - "DefaultGroupName": "Default"//默认分组名称 + "DocumentTitle": "Swagger", //默认标题 + "DefaultGroupName": "Default" //默认分组名称 }, "DynamicApiControllerSettings": { "DefaultRoutePrefix": "api", //默认路由前缀 @@ -33,8 +44,30 @@ "AsLowerCamelCase": true, //启用小驼峰命名(首字母小写) "UrlParameterization": true // 方法参数 }, - "AppSettings": { - "InjectSpecificationDocument": true // 生产环境是否开启Swagger + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + }, + "File": { + "Enabled": true, // 启用文件日志 + "FileName": "logs/{0:yyyyMMdd}_{1}.log", // 日志文件 + "Append": true, // 追加覆盖 + // "MinimumLevel": "Information", // 日志级别 + "FileSizeLimitBytes": 10485760, // 10M=10*1024*1024 + "MaxRollingFiles": 30 // 只保留30个文件 + }, + "Monitor": { + "GlobalEnabled": true, // 启用全局拦截日志 + "IncludeOfMethods": [], // 拦截特定方法,当GlobalEnabled=false有效 + "ExcludeOfMethods": [], // 排除特定方法,当GlobalEnabled=true有效 + "BahLogLevel": "Information", // Oops.Oh 和 Oops.Bah 业务日志输出级别 + "WithReturnValue": true, // 配置是否包含返回值,默认true + "ReturnValueThreshold": 0 // 配置返回值字符串阈值,默认0全量输出 + } + }, + "SnowId": { + "WorkerId": 5 // 取值范围0~63,默认1 }, "CorsAccessorSettings": { "WithExposedHeaders": [ @@ -43,4 +76,4 @@ "environment" ] } -} +} \ No newline at end of file diff --git a/Cis.Core/Util/RespParamProvider.cs b/Cis.Core/Entity/RespParamProvider.cs similarity index 100% rename from Cis.Core/Util/RespParamProvider.cs rename to Cis.Core/Entity/RespParamProvider.cs diff --git a/Cis.Web.Core/Startup.cs b/Cis.Web.Core/Startup.cs index 6f1206e..5248263 100644 --- a/Cis.Web.Core/Startup.cs +++ b/Cis.Web.Core/Startup.cs @@ -4,12 +4,16 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; +using System; +using System.IO; using Yitter.IdGenerator; namespace Cis.Web.Core; +[AppStartup(1000)] public class Startup : AppStartup { /// @@ -39,12 +43,30 @@ public class Startup : AppStartup .AddNewtonsoftJson(options => { options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); // 首字母小写(驼峰样式) + options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;// 设置本地时区 options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; // 时间格式化 options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; // 忽略循环引用 options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; // 忽略空值 }) .AddInjectWithUnifyResult(); + // 日志记录 + if (App.GetConfig("Logging:File:Enabled")) // 日志写入文件 + { + Array.ForEach(new[] { LogLevel.Information, LogLevel.Warning, LogLevel.Error }, logLevel => + { + services.AddFileLogging(options => + { + options.FileNameRule = fileName => string.Format(fileName, DateTime.Now, logLevel.ToString()); // 每天创建一个文件 + options.WriteFilter = logMsg => logMsg.LogLevel == logLevel; // 日志级别 + options.HandleWriteError = (writeError) => // 写入失败时启用备用文件 + { + writeError.UseRollbackFileName(Path.GetFileNameWithoutExtension(writeError.CurrentFileName) + "-oops" + Path.GetExtension(writeError.CurrentFileName)); + }; + }); + }); + } + // 配置雪花Id算法机器码 YitIdHelper.SetIdGenerator(new IdGeneratorOptions { diff --git a/Cis.Web.Entry/Cis.Web.Entry.csproj b/Cis.Web.Entry/Cis.Web.Entry.csproj index 2ddaf1d..6392984 100644 --- a/Cis.Web.Entry/Cis.Web.Entry.csproj +++ b/Cis.Web.Entry/Cis.Web.Entry.csproj @@ -10,8 +10,4 @@ - - - - diff --git a/Cis.Web.Entry/wwwroot/images/logo.png b/Cis.Web.Entry/wwwroot/images/logo.png new file mode 100644 index 0000000..eff5511 Binary files /dev/null and b/Cis.Web.Entry/wwwroot/images/logo.png differ