diff --git a/CoreCms.Net.Configuration/AppSettingsConstVars.cs b/CoreCms.Net.Configuration/AppSettingsConstVars.cs index 5652c5ba..1bcf6d87 100644 --- a/CoreCms.Net.Configuration/AppSettingsConstVars.cs +++ b/CoreCms.Net.Configuration/AppSettingsConstVars.cs @@ -96,6 +96,15 @@ namespace CoreCms.Net.Configuration /// 用户访问记录-过滤ip /// public static readonly string MiddlewareRecordAccessLogsIgnoreApis = AppSettingsHelper.GetContent("Middleware", "RecordAccessLogs", "IgnoreApis"); + /// + /// 是否开启记录到文件模式 + /// + public static readonly bool MiddlewareRecordAccessLogsEnabledFileMode = AppSettingsHelper.GetContent("Middleware", "RecordAccessLogs", "EnabledFileMode").ObjToBool(); + /// + /// 是否开启记录到数据库模式 + /// + public static readonly bool MiddlewareRecordAccessLogsEnabledDbMode = AppSettingsHelper.GetContent("Middleware", "RecordAccessLogs", "EnabledDbMode").ObjToBool(); + #endregion diff --git a/CoreCms.Net.Configuration/GlobalEnumVars.cs b/CoreCms.Net.Configuration/GlobalEnumVars.cs index cf485471..5e503b3b 100644 --- a/CoreCms.Net.Configuration/GlobalEnumVars.cs +++ b/CoreCms.Net.Configuration/GlobalEnumVars.cs @@ -5,10 +5,22 @@ namespace CoreCms.Net.Configuration /// /// 系统常用枚举类 /// - public class GlobalEnumVars + public static class GlobalEnumVars { #region 系统相关=============================================================== + /// + /// 多端划分 + /// + public enum CoreShopSystemCategory + { + Admin = 0, + Api = 1, + Pc = 2, + H5 = 3 + } + + /// /// 缓存优先级:低、普通、高、永不移除 /// diff --git a/CoreCms.Net.Filter/AdminsControllerPermission.cs b/CoreCms.Net.Filter/AdminsControllerPermission.cs index 34810d85..f188dcc4 100644 --- a/CoreCms.Net.Filter/AdminsControllerPermission.cs +++ b/CoreCms.Net.Filter/AdminsControllerPermission.cs @@ -15,88 +15,108 @@ using System.ComponentModel; using System.Linq; using System.Reflection; using System.Text; +using CoreCms.Net.Caching.Manual; +using CoreCms.Net.Caching.MemoryCache; +using CoreCms.Net.Configuration; namespace CoreCms.Net.Filter { - public class AdminsControllerPermission + public static class AdminsControllerPermission { + + /// + /// 缓存ActionPermission名称 + /// + private const string CacheCoreCmsActionPermission = "CacheCoreCmsActionPermission"; + /// + /// 缓存ControllerPermission名称 + /// + private const string CacheCoreCmsControllerPermission = "CacheCoreCmsControllerPermission"; + + /// /// 反射获取所有controller 和action /// /// - public static List GetAllControllerAndActionByAssembly() + private static ControllerPermissionResult GetAllControllerAndActionByAssembly() { - var result = new List(); var types = Assembly.Load("CoreCms.Net.Web.Admin").GetTypes(); - var noController = new[] { "ToolsController", "LoginController", "DemoController" }; + var acs = new List(); + var controllers = types.Where(p => p.Name.Contains("Controller") && !noController.Contains(p.Name)); foreach (var type in controllers) { - if (type.Name.Length > 10 && type.BaseType.Name == "ControllerBase" && type.Name.EndsWith("Controller")) //如果是Controller + if (type.BaseType != null && (type.Name.Length <= 10 || type.BaseType.Name != "ControllerBase" || !type.Name.EndsWith("Controller"))) continue; + + var members = type.GetMethods(); + var cp = new ControllerPermission(); + cp.name = type.Name.Substring(0, type.Name.Length - 10); + cp.action = new List(); + cp.controllerName = cp.name; + + var objs = type.GetCustomAttributes(typeof(DescriptionAttribute), true); + if (objs.Length > 0) cp.description = (objs[0] as DescriptionAttribute)?.Description; + //附加此代码用于代码生成器显示选择 + if (!string.IsNullOrEmpty(cp.description)) { - var members = type.GetMethods(); - var cp = new ControllerPermission - { - name = type.Name.Substring(0, type.Name.Length - 10), - action = new List() - }; - - var objs = type.GetCustomAttributes(typeof(DescriptionAttribute), true); - if (objs.Length > 0) cp.description = (objs[0] as DescriptionAttribute).Description; - - if (!string.IsNullOrEmpty(cp.description)) - { - cp.name += "【" + cp.description + "】"; - } - - - var newMembers = members.Where(p => - p.ReturnType.FullName != null && (p.ReturnType.Name == "ActionResult" || - p.ReturnType.Name == "FileResult" || - p.ReturnType.Name == "JsonResult" || - (p.ReturnType.GenericTypeArguments.Length > 0 && p.ReturnType.GenericTypeArguments[0].Name == "JsonResult") || - p.ReturnType.Name == "AdminUiCallBack" || - p.ReturnType.Name == "IActionResult" || - p.ReturnType.FullName.Contains("CoreCms.Net.Model.ViewModels.UI.AdminUiCallBack")) - ).ToList(); - - foreach (var member in newMembers) - { - if (member.Name == "ValidationProblem" || member.Name == "Json") continue; - - //if (member.ReturnType.Name == "ActionResult" || member.ReturnType.Name == "FileResult" || member.ReturnType.Name == "JsonResult" || (member.ReturnType.GenericTypeArguments.Length > 0 && member.ReturnType.GenericTypeArguments[0].Name == "JsonResult")) //如果是Action - //{ - //} - - - var ap = new ActionPermission - { - name = member.Name, - actionName = member.Name, - controllerName = member.DeclaringType.Name.Substring(0, member.DeclaringType.Name.Length - 10) - }; - // 去掉“Controller”后缀 - - var attrs = member.GetCustomAttributes(typeof(DescriptionAttribute), true); - if (attrs.Length > 0) ap.description = (attrs[0] as DescriptionAttribute).Description; - - if (!string.IsNullOrEmpty(ap.description)) - { - ap.name += "【" + ap.description + "】"; - } - cp.action.Add(ap); - - } - cp.action = cp.action.Distinct(new ModelComparer()).ToList(); - result.Add(cp); + cp.name += "【" + cp.description + "】"; } + + var newMembers = members.Where(p => + p.ReturnType.FullName != null && (p.ReturnType.Name == "ActionResult" || + p.ReturnType.Name == "FileResult" || + p.ReturnType.Name == "JsonResult" || + (p.ReturnType.GenericTypeArguments.Length > 0 && p.ReturnType.GenericTypeArguments[0].Name == "JsonResult") || + p.ReturnType.Name == "AdminUiCallBack" || + p.ReturnType.Name == "IActionResult" || + p.ReturnType.FullName.Contains("CoreCms.Net.Model.ViewModels.UI.AdminUiCallBack")) + ).ToList(); + + foreach (var member in newMembers) + { + if (member.Name == "ValidationProblem" || member.Name == "Json") continue; + + //if (member.ReturnType.Name == "ActionResult" || member.ReturnType.Name == "FileResult" || member.ReturnType.Name == "JsonResult" || (member.ReturnType.GenericTypeArguments.Length > 0 && member.ReturnType.GenericTypeArguments[0].Name == "JsonResult")) //如果是Action + //{ + //} + + var ap = new ActionPermission(); + ap.name = member.Name; + ap.actionName = member.Name; + if (member.DeclaringType != null) + { + // 去掉“Controller”后缀 + ap.controllerName = member.DeclaringType.Name.Substring(0, member.DeclaringType.Name.Length - 10); + } + ap.path = "/Api/" + ap.controllerName + "/" + member.Name; + + var attrs = member.GetCustomAttributes(typeof(DescriptionAttribute), true); + if (attrs.Length > 0) ap.description = (attrs[0] as DescriptionAttribute)?.Description; + //附加此代码用于代码生成器显示选择 + if (!string.IsNullOrEmpty(ap.description)) + { + ap.name += "【" + ap.description + "】"; + } + ap.controllerDescription = cp.description; + + cp.action.Add(ap); + acs.Add(ap); + } + cp.action = cp.action.Distinct(new ModelComparer()).ToList(); + result.Add(cp); } - return result; + + var resultObj = new ControllerPermissionResult + { + ControllersAndActions = result, + Actions = acs + }; + return resultObj; } private class ModelComparer : IEqualityComparer @@ -111,46 +131,132 @@ namespace CoreCms.Net.Filter return obj.name.ToUpper().GetHashCode(); } } + + /// + /// 获取缓存ActionPermission + /// + /// + public static List GetCacheCoreCmsActionPermission() + { + var memoryCacheManager = new MemoryCacheManager(); + var cache = memoryCacheManager.Get>(CacheCoreCmsActionPermission); + return cache ?? UpdateCacheCoreCmsActionPermission().Actions; + } + + /// + /// 获取缓存ControllerPermission名称 + /// + /// + public static List GetCacheCoreCmsControllerPermission() + { + var memoryCacheManager = new MemoryCacheManager(); + var cache = memoryCacheManager.Get>(CacheCoreCmsControllerPermission); + return cache ?? UpdateCacheCoreCmsActionPermission().ControllersAndActions; + } + + /// + /// 更新cache + /// + private static ControllerPermissionResult UpdateCacheCoreCmsActionPermission() + { + var list = GetAllControllerAndActionByAssembly(); + var memoryCacheManager = new MemoryCacheManager(); + //缓存24小时 + memoryCacheManager.Set(CacheCoreCmsControllerPermission, list.ControllersAndActions, 1440); + memoryCacheManager.Set(CacheCoreCmsActionPermission, list.Actions, 1440); + return list; + } } - - public class ActionPermission + /// + /// 外部包一圈 + /// + public class ControllerPermissionResult { /// - /// 请求地址 + /// 实际结果集 /// - public virtual string name { get; set; } + public List ControllersAndActions { get; set; } /// - /// 请求地址 + /// 只获取的action集合,用于缓存 /// - public virtual string controllerName { get; set; } + public List Actions { get; set; } + + } + + /// + /// action数据 + /// + public sealed class ActionPermission + { + /// + /// 地址 + /// + public string path { get; set; } /// - /// 请求地址 + /// 地址及描述 /// - public virtual string actionName { get; set; } + public string name { get; set; } + + /// + /// 控制器 + /// + public string controllerName { get; set; } + + /// + /// 控制器描述 + /// + public string controllerDescription { get; set; } + + /// + /// 方法 + /// + public string actionName { get; set; } /// /// 描述 /// - public virtual string description { get; set; } + public string description { get; set; } - public virtual string type { get; set; } = "action"; + /// + /// 类型 + /// + public string type { get; set; } = "action"; } - public class ControllerPermission + /// + /// Controller数据 + /// + public sealed class ControllerPermission { - public virtual string name { get; set; } + /// + /// 控制器 + /// + public string controllerName { get; set; } - public virtual string description { get; set; } + /// + /// 控制器和描述 + /// + public string name { get; set; } - public virtual IList action { get; set; } + /// + /// 描述 + /// + public string description { get; set; } + /// + /// 方法列表 + /// + public IList action { get; set; } - public virtual string type { get; set; } = "controller"; + /// + /// 类型 + /// + public string type { get; set; } = "controller"; } } diff --git a/CoreCms.Net.Filter/CoreCms.Net.Filter.csproj b/CoreCms.Net.Filter/CoreCms.Net.Filter.csproj index 79506632..f9e96bae 100644 --- a/CoreCms.Net.Filter/CoreCms.Net.Filter.csproj +++ b/CoreCms.Net.Filter/CoreCms.Net.Filter.csproj @@ -11,6 +11,7 @@ + diff --git a/CoreCms.Net.IRepository/System/ISysUserOperationLogRepository.cs b/CoreCms.Net.IRepository/System/ISysUserOperationLogRepository.cs new file mode 100644 index 00000000..6b3f95eb --- /dev/null +++ b/CoreCms.Net.IRepository/System/ISysUserOperationLogRepository.cs @@ -0,0 +1,44 @@ +/*********************************************************************** + * Project: CoreCms + * ProjectName: 核心内容管理系统 + * Web: https://www.corecms.net + * Author: 大灰灰 + * Email: jianweie@163.com + * CreateTime: 2022/4/10 0:27:47 + * Description: 暂无 + ***********************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading.Tasks; +using CoreCms.Net.Model.Entities; +using CoreCms.Net.Model.ViewModels.Basics; +using CoreCms.Net.Model.ViewModels.UI; +using SqlSugar; + + +namespace CoreCms.Net.IRepository +{ + /// + /// 用户操作日志 工厂接口 + /// + public interface ISysUserOperationLogRepository : IBaseRepository + { + /// + /// 重写根据条件查询分页数据 + /// + /// 判断集合 + /// 排序方式 + /// 当前页面索引 + /// 分布大小 + /// + /// 是否使用WITH(NOLOCK) + /// + new Task> QueryPageAsync( + Expression> predicate, + Expression> orderByExpression, OrderByType orderByType, int pageIndex = 1, + int pageSize = 20, bool blUseNoLock = false); + + } +} diff --git a/CoreCms.Net.IServices/System/ISysUserOperationLogServices.cs b/CoreCms.Net.IServices/System/ISysUserOperationLogServices.cs new file mode 100644 index 00000000..da7dd4b6 --- /dev/null +++ b/CoreCms.Net.IServices/System/ISysUserOperationLogServices.cs @@ -0,0 +1,44 @@ +/*********************************************************************** + * Project: CoreCms + * ProjectName: 核心内容管理系统 + * Web: https://www.corecms.net + * Author: 大灰灰 + * Email: jianweie@163.com + * CreateTime: 2022/4/10 0:27:47 + * Description: 暂无 + ***********************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading.Tasks; +using CoreCms.Net.Model.Entities; +using CoreCms.Net.Model.ViewModels.Basics; +using CoreCms.Net.Model.ViewModels.UI; +using SqlSugar; + +namespace CoreCms.Net.IServices +{ + /// + /// 用户操作日志 服务工厂接口 + /// + public interface ISysUserOperationLogServices : IBaseServices + { + #region 重写根据条件查询分页数据 + /// + /// 重写根据条件查询分页数据 + /// + /// 判断集合 + /// 排序方式 + /// 当前页面索引 + /// 分布大小 + /// + /// 是否使用WITH(NOLOCK) + /// + new Task> QueryPageAsync( + Expression> predicate, + Expression> orderByExpression, OrderByType orderByType, int pageIndex = 1, + int pageSize = 20, bool blUseNoLock = false); + #endregion + } +} diff --git a/CoreCms.Net.Middlewares/CoreCms.Net.Middlewares.csproj b/CoreCms.Net.Middlewares/CoreCms.Net.Middlewares.csproj index cc4bad31..394ce2ef 100644 --- a/CoreCms.Net.Middlewares/CoreCms.Net.Middlewares.csproj +++ b/CoreCms.Net.Middlewares/CoreCms.Net.Middlewares.csproj @@ -8,6 +8,7 @@ + diff --git a/CoreCms.Net.Middlewares/ExceptionHandlerMiddForAdmin.cs b/CoreCms.Net.Middlewares/ExceptionHandlerMiddForAdmin.cs index c86ec506..77a7046e 100644 --- a/CoreCms.Net.Middlewares/ExceptionHandlerMiddForAdmin.cs +++ b/CoreCms.Net.Middlewares/ExceptionHandlerMiddForAdmin.cs @@ -13,60 +13,57 @@ using System; -using System.Collections.Generic; using System.Net; -using System.Text; using System.Threading.Tasks; using CoreCms.Net.Loging; using CoreCms.Net.Model.ViewModels.UI; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Logging; using Newtonsoft.Json; +using NLog; -namespace CoreCms.Net.Middlewares +namespace CoreCms.Net.Middlewares; + +/// +/// 异常错误统一返回记录 +/// +public class ExceptionHandlerMiddForAdmin { - /// - /// 异常错误统一返回记录 - /// - public class ExceptionHandlerMiddForAdmin + private readonly RequestDelegate _next; + + public ExceptionHandlerMiddForAdmin(RequestDelegate next) { - private readonly RequestDelegate _next; + _next = next; + } - public ExceptionHandlerMiddForAdmin(RequestDelegate next) + public async Task Invoke(HttpContext context) + { + try { - _next = next; + await _next(context); } - - public async Task Invoke(HttpContext context) + catch (Exception ex) { - try - { - await _next(context); - } - catch (Exception ex) - { - await HandleExceptionAsync(context, ex); - } - } - - private async Task HandleExceptionAsync(HttpContext context, Exception ex) - { - if (ex == null) return; - NLogUtil.WriteAll(NLog.LogLevel.Error, LogType.Web, "全局捕获异常", "全局捕获异常", new Exception("全局捕获异常", ex)); - await WriteExceptionAsync(context, ex).ConfigureAwait(false); - } - - private static async Task WriteExceptionAsync(HttpContext context, Exception e) - { - if (e is UnauthorizedAccessException) context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; - else if (e is Exception) context.Response.StatusCode = (int)HttpStatusCode.BadRequest; - - context.Response.ContentType = "application/json"; - var jm = new AdminUiCallBack(); - jm.code = 500; - jm.data = e; - jm.msg = "全局捕获异常"; - await context.Response.WriteAsync(JsonConvert.SerializeObject(jm)).ConfigureAwait(false); + await HandleExceptionAsync(context, ex); } } -} + + private async Task HandleExceptionAsync(HttpContext context, Exception ex) + { + if (ex == null) return; + NLogUtil.WriteAll(LogLevel.Error, LogType.Web, "全局捕获异常", "全局捕获异常", new Exception("全局捕获异常", ex)); + await WriteExceptionAsync(context, ex).ConfigureAwait(false); + } + + private static async Task WriteExceptionAsync(HttpContext context, Exception e) + { + if (e is UnauthorizedAccessException) context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; + else if (e != null) context.Response.StatusCode = (int)HttpStatusCode.BadRequest; + + context.Response.ContentType = "application/json"; + var jm = new AdminUiCallBack(); + jm.code = 500; + jm.data = e; + jm.msg = "全局捕获异常"; + await context.Response.WriteAsync(JsonConvert.SerializeObject(jm)).ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/CoreCms.Net.Middlewares/ExceptionHandlerMiddForClent.cs b/CoreCms.Net.Middlewares/ExceptionHandlerMiddForClent.cs index e8dd1a40..6acf793d 100644 --- a/CoreCms.Net.Middlewares/ExceptionHandlerMiddForClent.cs +++ b/CoreCms.Net.Middlewares/ExceptionHandlerMiddForClent.cs @@ -13,69 +13,63 @@ using System; -using System.Collections.Generic; using System.Net; -using System.Text; using System.Threading.Tasks; -using CoreCms.Net.IServices; using CoreCms.Net.Loging; -using CoreCms.Net.Model.Entities; using CoreCms.Net.Model.ViewModels.UI; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Logging; -using Microsoft.Net.Http.Headers; using Newtonsoft.Json; +using NLog; -namespace CoreCms.Net.Middlewares +namespace CoreCms.Net.Middlewares; + +/// +/// 异常错误统一返回记录 +/// +public class ExceptionHandlerMiddForClent { - /// - /// 异常错误统一返回记录 - /// - public class ExceptionHandlerMiddForClent + private readonly RequestDelegate _next; + + + public ExceptionHandlerMiddForClent(RequestDelegate next) { - private readonly RequestDelegate _next; + _next = next; + } - - public ExceptionHandlerMiddForClent(RequestDelegate next) + public async Task Invoke(HttpContext context) + { + try { - _next = next; + await _next(context); } - - public async Task Invoke(HttpContext context) + catch (Exception ex) { - try - { - await _next(context); - } - catch (Exception ex) - { - await HandleExceptionAsync(context, ex); - } - } - - private async Task HandleExceptionAsync(HttpContext context, Exception ex) - { - if (ex == null) return; - - NLogUtil.WriteAll(NLog.LogLevel.Error, LogType.ApiRequest, "全局捕获异常", "全局捕获异常", new Exception("全局捕获异常", ex)); - - await WriteExceptionAsync(context, ex).ConfigureAwait(false); - } - - private static async Task WriteExceptionAsync(HttpContext context, Exception e) - { - if (e is UnauthorizedAccessException) - context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; - else if (e is Exception) - context.Response.StatusCode = (int)HttpStatusCode.BadRequest; - - context.Response.ContentType = "application/json"; - var jm = new WebApiCallBack(); - jm.status = false; - jm.code = 500; - jm.data = e; - jm.msg = "全局数据异常"; - await context.Response.WriteAsync(JsonConvert.SerializeObject(jm)).ConfigureAwait(false); + await HandleExceptionAsync(context, ex); } } -} + + private async Task HandleExceptionAsync(HttpContext context, Exception ex) + { + if (ex == null) return; + + NLogUtil.WriteAll(LogLevel.Error, LogType.ApiRequest, "全局捕获异常", "全局捕获异常", new Exception("全局捕获异常", ex)); + + await WriteExceptionAsync(context, ex).ConfigureAwait(false); + } + + private static async Task WriteExceptionAsync(HttpContext context, Exception e) + { + if (e is UnauthorizedAccessException) + context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; + else if (e != null) + context.Response.StatusCode = (int)HttpStatusCode.BadRequest; + + context.Response.ContentType = "application/json"; + var jm = new WebApiCallBack(); + jm.status = false; + jm.code = 500; + jm.data = e; + jm.msg = "全局数据异常"; + await context.Response.WriteAsync(JsonConvert.SerializeObject(jm)).ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/CoreCms.Net.Middlewares/IPLogMildd.cs b/CoreCms.Net.Middlewares/IPLogMildd.cs index 1bf81cd5..468b82e1 100644 --- a/CoreCms.Net.Middlewares/IPLogMildd.cs +++ b/CoreCms.Net.Middlewares/IPLogMildd.cs @@ -67,9 +67,9 @@ namespace CoreCms.Net.Middlewares if (!string.IsNullOrEmpty(requestInfo)) { - Parallel.For(0, 1, e => + Parallel.For(0, 1, _ => { - LogLockHelper.OutSql2Log("RequestIpInfoLog", "RequestIpInfoLog" + dt.ToString("yyyy-MM-dd-HH"), new string[] { requestInfo + "," }, false); + LogLockHelper.OutSql2Log("RequestIpInfoLog", "RequestIpInfoLog" + dt.ToString("yyyy-MM-dd-HH"), new[] { requestInfo + "," }, false); }); request.Body.Position = 0; } @@ -77,6 +77,7 @@ namespace CoreCms.Net.Middlewares } catch (Exception) { + // ignored } } else @@ -95,10 +96,7 @@ namespace CoreCms.Net.Middlewares var ip = context.Request.Headers["X-Forwarded-For"].ObjectToString(); if (string.IsNullOrEmpty(ip)) { - if (context.Connection.RemoteIpAddress != null) - { - ip = context.Connection.RemoteIpAddress.MapToIPv4().ObjectToString(); - } + ip = context.Connection.RemoteIpAddress.ObjectToString(); } return ip; } diff --git a/CoreCms.Net.Middlewares/MiddlewareHelpers.cs b/CoreCms.Net.Middlewares/MiddlewareHelpers.cs index 8ab90028..76eda593 100644 --- a/CoreCms.Net.Middlewares/MiddlewareHelpers.cs +++ b/CoreCms.Net.Middlewares/MiddlewareHelpers.cs @@ -78,10 +78,11 @@ namespace CoreCms.Net.Middlewares /// 用户访问接口日志中间件 /// /// + /// /// - public static IApplicationBuilder UseRecordAccessLogsMildd(this IApplicationBuilder app) + public static IApplicationBuilder UseRecordAccessLogsMildd(this IApplicationBuilder app,string dataSources) { - return app.UseMiddleware(); + return app.UseMiddleware(dataSources); } } diff --git a/CoreCms.Net.Middlewares/RecordAccessLogsMildd.cs b/CoreCms.Net.Middlewares/RecordAccessLogsMildd.cs index f0b34197..7dbb1c54 100644 --- a/CoreCms.Net.Middlewares/RecordAccessLogsMildd.cs +++ b/CoreCms.Net.Middlewares/RecordAccessLogsMildd.cs @@ -3,15 +3,24 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System; +using System.Collections.Generic; using System.Diagnostics; +using System.IdentityModel.Tokens.Jwt; using System.IO; +using System.Linq; +using System.Security.Claims; using System.Text; using System.Threading.Tasks; using System.Web; -using CoreCms.Net.Auth.HttpContextUser; using CoreCms.Net.Configuration; +using CoreCms.Net.Filter; +using CoreCms.Net.IServices; using CoreCms.Net.Loging; +using CoreCms.Net.Model.Entities; +using CoreCms.Net.Model.ViewModels.Basics; using CoreCms.Net.Utility.Extensions; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.JwtBearer; namespace CoreCms.Net.Middlewares { @@ -21,103 +30,143 @@ namespace CoreCms.Net.Middlewares /// public class RecordAccessLogsMildd { - /// - /// - /// private readonly RequestDelegate _next; - private readonly IHttpContextUser _user; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ISysUserOperationLogServices _sysUserOperationLogServices; - private readonly ILogger _logger; private readonly Stopwatch _stopwatch; + private readonly string _dataSources; + + /// /// 构造 /// - /// - /// - /// - public RecordAccessLogsMildd(RequestDelegate next, IHttpContextUser user, ILogger logger) + public RecordAccessLogsMildd(RequestDelegate next, IHttpContextAccessor httpContextAccessor, ISysUserOperationLogServices sysUserOperationLogServices, string dataSources) { _next = next; - _user = user; - _logger = logger; + _httpContextAccessor = httpContextAccessor; + _dataSources = dataSources; + _sysUserOperationLogServices = sysUserOperationLogServices; _stopwatch = new Stopwatch(); } public async Task InvokeAsync(HttpContext context) { - if (AppSettingsConstVars.MiddlewareRecordAccessLogsEnabled) + //用户访问记录-是否开启 + var middlewareRecordAccessLogsEnabled = AppSettingsConstVars.MiddlewareRecordAccessLogsEnabled; + //是否开启记录到文件模式 + var middlewareRecordAccessLogsEnabledFileMode = AppSettingsConstVars.MiddlewareRecordAccessLogsEnabledFileMode; + //是否开启记录到数据库模式 + var middlewareRecordAccessLogsEnabledDbMode = AppSettingsConstVars.MiddlewareRecordAccessLogsEnabledDbMode; + + if (middlewareRecordAccessLogsEnabled && (middlewareRecordAccessLogsEnabledFileMode || middlewareRecordAccessLogsEnabledDbMode)) { - var api = context.Request.Path.ObjectToString().TrimEnd('/').ToLower(); + var request = context.Request; + var api = request.Path.ObjectToString().TrimEnd('/').ToLower(); var ignoreApis = AppSettingsConstVars.MiddlewareRecordAccessLogsIgnoreApis; // 过滤,只有接口 - if (api.Contains("api") && !ignoreApis.Contains(api)) + if (api.Contains("api") && !ignoreApis.ToLower().Contains(api)) { _stopwatch.Restart(); - var userAccessModel = new UserAccessModel(); + var uLog = new SysUserOperationLog(); - HttpRequest request = context.Request; - - userAccessModel.API = api; - userAccessModel.User = _user.Name; - userAccessModel.IP = IPLogMildd.GetClientIp(context); - userAccessModel.BeginTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); - userAccessModel.RequestMethod = request.Method; - userAccessModel.Agent = request.Headers["User-Agent"].ObjectToString(); - - - // 获取请求body内容 - if (request.Method.ToLower().Equals("post") || request.Method.ToLower().Equals("put")) + if (_httpContextAccessor.HttpContext != null) { - // 启用倒带功能,就可以让 Request.Body 可以再次读取 - request.EnableBuffering(); + var authenticate = await _httpContextAccessor.HttpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme); + if (authenticate.Succeeded && authenticate.Principal != null) + { + //账号 + uLog.userName = authenticate.Principal.Identities.First().FindFirst(ClaimTypes.Name)?.Value; + //昵称 + uLog.userNickName = authenticate.Principal.Identities.First().FindFirst(ClaimTypes.GivenName)?.Value; + //用户序列 + uLog.userId = authenticate.Principal.Identities.First().FindFirst(JwtRegisteredClaimNames.Jti)!.Value.ObjectToInt(0); + } - Stream stream = request.Body; - byte[] buffer = new byte[request.ContentLength.Value]; - stream.Read(buffer, 0, buffer.Length); - userAccessModel.RequestData = Encoding.UTF8.GetString(buffer); + var adminLog = AdminsControllerPermission.GetCacheCoreCmsActionPermission(); - request.Body.Position = 0; + var curLog = adminLog.FirstOrDefault(p => p.path.ToLower() == _httpContextAccessor.HttpContext.Request.Path.Value.ToLower()); + if (curLog != null) + { + uLog.actionName = curLog.actionName; + uLog.actionDescription = curLog.description; + uLog.controllerName = curLog.controllerName; + uLog.controllerDescription = curLog.controllerDescription; + } + uLog.apiPath = _httpContextAccessor.HttpContext.Request.Path.Value; + uLog.statusCode = _httpContextAccessor.HttpContext.Response.StatusCode; } - else if (request.Method.ToLower().Equals("get") || request.Method.ToLower().Equals("delete")) + else { - userAccessModel.RequestData = HttpUtility.UrlDecode(request.QueryString.ObjectToString(), Encoding.UTF8); + uLog.apiPath = api; + } + + uLog.ip = IPLogMildd.GetClientIp(context); + uLog.beginTime = DateTime.Now; + uLog.requestMethod = request.Method; + uLog.agent = request.Headers["User-Agent"].ObjectToString(); + uLog.dataSources = _dataSources; + + switch (request.Method.ToLower()) + { + // 获取请求body内容 + case "post": + case "put": + { + // 启用倒带功能,就可以让 Request.Body 可以再次读取 + request.EnableBuffering(); + var stream = request.Body; + if (request.ContentLength != null) + { + byte[] buffer = new byte[request.ContentLength.Value]; + var read = await stream.ReadAsync(buffer); + uLog.requestData = Encoding.UTF8.GetString(buffer); + } + request.Body.Position = 0; + break; + } + case "get": + case "delete": + uLog.requestData = HttpUtility.UrlDecode(request.QueryString.ObjectToString(), Encoding.UTF8); + break; } // 获取Response.Body内容 var originalBodyStream = context.Response.Body; - using (var responseBody = new MemoryStream()) + await using (var responseBody = new MemoryStream()) { context.Response.Body = responseBody; - await _next(context); - - var responseBodyData = await GetResponse(context.Response); - + uLog.responseBodyData = await GetResponse(context.Response); await responseBody.CopyToAsync(originalBodyStream); } - - var dt = DateTime.Now; - // 响应完成记录时间和存入日志 - context.Response.OnCompleted(() => + context.Response.OnCompleted(async () => { _stopwatch.Stop(); - userAccessModel.OPTime = _stopwatch.ElapsedMilliseconds + "ms"; - - // 自定义log输出 - var requestInfo = JsonConvert.SerializeObject(userAccessModel); - Parallel.For(0, 1, e => + uLog.opTime = _stopwatch.ElapsedMilliseconds + "ms"; + uLog.endTime = DateTime.Now; + uLog.createTime = DateTime.Now; + //写入文件 + if (middlewareRecordAccessLogsEnabledFileMode) { - LogLockHelper.OutSql2Log("RecordAccessLogs", "RecordAccessLogs" + dt.ToString("yyyy-MM-dd-HH"), new string[] { requestInfo + "," }, false); - }); - - return Task.CompletedTask; + // 自定义log输出 + var requestInfo = JsonConvert.SerializeObject(uLog); + Parallel.For(0, 1, e => + { + LogLockHelper.OutSql2Log("RecordAccessLogs", "RecordAccessLogs" + DateTime.Now.ToString("yyyy-MM-dd-HH"), new[] { requestInfo + "," }, false); + }); + } + //写入数据库 + if (middlewareRecordAccessLogsEnabledDbMode) + { + await _sysUserOperationLogServices.InsertAsync(uLog); + } }); - } else { @@ -145,18 +194,5 @@ namespace CoreCms.Net.Middlewares } } - public class UserAccessModel - { - public string User { get; set; } - public string IP { get; set; } - public string API { get; set; } - public string BeginTime { get; set; } - public string OPTime { get; set; } - public string RequestMethod { get; set; } - public string RequestData { get; set; } - public string Agent { get; set; } - - } - } diff --git a/CoreCms.Net.Middlewares/RequRespLogMildd.cs b/CoreCms.Net.Middlewares/RequRespLogMildd.cs index 649a101a..627654e1 100644 --- a/CoreCms.Net.Middlewares/RequRespLogMildd.cs +++ b/CoreCms.Net.Middlewares/RequRespLogMildd.cs @@ -48,7 +48,7 @@ namespace CoreCms.Net.Middlewares if (AppSettingsConstVars.MiddlewareRequestResponseLogEnabled) { // 过滤,只有接口 - if (context.Request.Path.Value.Contains("api") || context.Request.Path.Value.Contains("Api")) + if (context.Request.Path.Value != null && (context.Request.Path.Value.Contains("api") || context.Request.Path.Value.Contains("Api"))) { context.Request.EnableBuffering(); Stream originalBody = context.Response.Body; @@ -57,18 +57,16 @@ namespace CoreCms.Net.Middlewares // 存储请求数据 await RequestDataLog(context); - using (var ms = new MemoryStream()) - { - context.Response.Body = ms; + await using var ms = new MemoryStream(); + context.Response.Body = ms; - await _next(context); + await _next(context); - // 存储响应数据 - ResponseDataLog(context.Response, ms); + // 存储响应数据 + ResponseDataLog(ms); - ms.Position = 0; - await ms.CopyToAsync(originalBody); - } + ms.Position = 0; + await ms.CopyToAsync(originalBody); } catch (Exception) { @@ -91,7 +89,7 @@ namespace CoreCms.Net.Middlewares } } - private async Task RequestDataLog(HttpContext context) + private static async Task RequestDataLog(HttpContext context) { var request = context.Request; var sr = new StreamReader(request.Body); @@ -100,9 +98,9 @@ namespace CoreCms.Net.Middlewares if (!string.IsNullOrEmpty(content)) { - Parallel.For(0, 1, e => + Parallel.For(0, 1, _ => { - LogLockHelper.OutSql2Log("RequestResponseLog", "RequestResponseLog" + DateTime.Now.ToString("yyyy-MM-dd-HH"), new string[] { "Request Data:", content }); + LogLockHelper.OutSql2Log("RequestResponseLog", "RequestResponseLog" + DateTime.Now.ToString("yyyy-MM-dd-HH"), new[] { "Request Data:", content }); }); @@ -110,18 +108,15 @@ namespace CoreCms.Net.Middlewares } } - private void ResponseDataLog(HttpResponse response, MemoryStream ms) + private static void ResponseDataLog(Stream ms) { ms.Position = 0; - var ResponseBody = new StreamReader(ms).ReadToEnd(); - // 去除 Html - var reg = "<[^>]+>"; - var isHtml = Regex.IsMatch(ResponseBody, reg); - if (!string.IsNullOrEmpty(ResponseBody)) + var responseBody = new StreamReader(ms).ReadToEnd(); + if (!string.IsNullOrEmpty(responseBody)) { - Parallel.For(0, 1, e => + Parallel.For(0, 1, _ => { - LogLockHelper.OutSql2Log("RequestResponseLog", "RequestResponseLog" + DateTime.Now.ToString("yyyy-MM-dd-HH"), new string[] { "Response Data:", ResponseBody }); + LogLockHelper.OutSql2Log("RequestResponseLog", "RequestResponseLog" + DateTime.Now.ToString("yyyy-MM-dd-HH"), new[] { "Response Data:", responseBody }); }); } } diff --git a/CoreCms.Net.Model/Entities/System/SysUserOperationLog.cs b/CoreCms.Net.Model/Entities/System/SysUserOperationLog.cs new file mode 100644 index 00000000..629878c4 --- /dev/null +++ b/CoreCms.Net.Model/Entities/System/SysUserOperationLog.cs @@ -0,0 +1,272 @@ +/*********************************************************************** + * Project: CoreCms + * ProjectName: 核心内容管理系统 + * Web: https://www.corecms.net + * Author: 大灰灰 + * Email: jianweie@163.com + * CreateTime: 2022/4/10 0:52:14 + * Description: 暂无 + ***********************************************************************/ + +using SqlSugar; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; + +namespace CoreCms.Net.Model.Entities +{ + /// + /// 用户操作日志 + /// + public partial class SysUserOperationLog + { + /// + /// 构造函数 + /// + public SysUserOperationLog() + { + } + + /// + /// 序列 + /// + [Display(Name = "序列")] + + [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] + + [Required(ErrorMessage = "请输入{0}")] + + + + public System.Int32 id { get; set; } + + + /// + /// 用户登录账号 + /// + [Display(Name = "用户登录账号")] + + + [StringLength(maximumLength:50,ErrorMessage = "{0}不能超过{1}字")] + + + public System.String userName { get; set; } + + + /// + /// 用户登录昵称 + /// + [Display(Name = "用户登录昵称")] + + + [StringLength(maximumLength:50,ErrorMessage = "{0}不能超过{1}字")] + + + public System.String userNickName { get; set; } + + + /// + /// 用户序列 + /// + [Display(Name = "用户序列")] + + [Required(ErrorMessage = "请输入{0}")] + + + + public System.Int32 userId { get; set; } + + + /// + /// IP地址 + /// + [Display(Name = "IP地址")] + + + [StringLength(maximumLength:150,ErrorMessage = "{0}不能超过{1}字")] + + + public System.String ip { get; set; } + + + /// + /// 请求地址 + /// + [Display(Name = "请求地址")] + + + [StringLength(maximumLength:150,ErrorMessage = "{0}不能超过{1}字")] + + + public System.String apiPath { get; set; } + + + /// + /// 开始时间 + /// + [Display(Name = "开始时间")] + + [Required(ErrorMessage = "请输入{0}")] + + + + public System.DateTime beginTime { get; set; } + + + /// + /// 结束时间 + /// + [Display(Name = "结束时间")] + + [Required(ErrorMessage = "请输入{0}")] + + + + public System.DateTime endTime { get; set; } + + + /// + /// 耗时 + /// + [Display(Name = "耗时")] + + + [StringLength(maximumLength:50,ErrorMessage = "{0}不能超过{1}字")] + + + public System.String opTime { get; set; } + + + /// + /// 请求方式 + /// + [Display(Name = "请求方式")] + + + [StringLength(maximumLength:50,ErrorMessage = "{0}不能超过{1}字")] + + + public System.String requestMethod { get; set; } + + + /// + /// 请求数据 + /// + [Display(Name = "请求数据")] + + + + + + public System.String requestData { get; set; } + + + /// + /// 返回数据 + /// + [Display(Name = "返回数据")] + + + + + + public System.String responseBodyData { get; set; } + + + /// + /// 代理渠道 + /// + [Display(Name = "代理渠道")] + + + [StringLength(maximumLength:1000,ErrorMessage = "{0}不能超过{1}字")] + + + public System.String agent { get; set; } + + + /// + /// 动作方法名称 + /// + [Display(Name = "动作方法名称")] + + + [StringLength(maximumLength:50,ErrorMessage = "{0}不能超过{1}字")] + + + public System.String actionName { get; set; } + + + /// + /// 动作方法描述 + /// + [Display(Name = "动作方法描述")] + + + [StringLength(maximumLength:50,ErrorMessage = "{0}不能超过{1}字")] + + + public System.String actionDescription { get; set; } + + + /// + /// 控制器名称 + /// + [Display(Name = "控制器名称")] + + + [StringLength(maximumLength:50,ErrorMessage = "{0}不能超过{1}字")] + + + public System.String controllerName { get; set; } + + + /// + /// 控制器名称 + /// + [Display(Name = "控制器名称")] + + + [StringLength(maximumLength:50,ErrorMessage = "{0}不能超过{1}字")] + + + public System.String controllerDescription { get; set; } + + + /// + /// 状态码 + /// + [Display(Name = "状态码")] + + [Required(ErrorMessage = "请输入{0}")] + + + + public System.Int32 statusCode { get; set; } + + + /// + /// 创建时间 + /// + [Display(Name = "创建时间")] + + [Required(ErrorMessage = "请输入{0}")] + + + + public System.DateTime createTime { get; set; } + + + /// + /// 数据来源 + /// + [Display(Name = "数据来源")] + + + [StringLength(maximumLength:50,ErrorMessage = "{0}不能超过{1}字")] + + + public System.String dataSources { get; set; } + + + } +} diff --git a/CoreCms.Net.Repository/System/SysUserOperationLogRepository.cs b/CoreCms.Net.Repository/System/SysUserOperationLogRepository.cs new file mode 100644 index 00000000..57dd7bf1 --- /dev/null +++ b/CoreCms.Net.Repository/System/SysUserOperationLogRepository.cs @@ -0,0 +1,119 @@ +/*********************************************************************** + * Project: CoreCms + * ProjectName: 核心内容管理系统 + * Web: https://www.corecms.net + * Author: 大灰灰 + * Email: jianweie@163.com + * CreateTime: 2022/4/10 0:27:47 + * Description: 暂无 + ***********************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading.Tasks; +using CoreCms.Net.Caching.Manual; +using CoreCms.Net.Configuration; +using CoreCms.Net.Model.Entities; +using CoreCms.Net.Model.ViewModels.Basics; +using CoreCms.Net.IRepository; +using CoreCms.Net.IRepository.UnitOfWork; +using CoreCms.Net.Model.ViewModels.UI; +using SqlSugar; + +namespace CoreCms.Net.Repository +{ + /// + /// 用户操作日志 接口实现 + /// + public class SysUserOperationLogRepository : BaseRepository, ISysUserOperationLogRepository + { + private readonly IUnitOfWork _unitOfWork; + public SysUserOperationLogRepository(IUnitOfWork unitOfWork) : base(unitOfWork) + { + _unitOfWork = unitOfWork; + } + + #region 重写根据条件查询分页数据 + /// + /// 重写根据条件查询分页数据 + /// + /// 判断集合 + /// 排序方式 + /// 当前页面索引 + /// 分布大小 + /// + /// 是否使用WITH(NOLOCK) + /// + public new async Task> QueryPageAsync(Expression> predicate, + Expression> orderByExpression, OrderByType orderByType, int pageIndex = 1, + int pageSize = 20, bool blUseNoLock = false) + { + RefAsync totalCount = 0; + List page; + if (blUseNoLock) + { + page = await DbClient.Queryable() + .OrderByIF(orderByExpression != null, orderByExpression, orderByType) + .WhereIF(predicate != null, predicate).Select(p => new SysUserOperationLog + { + id = p.id, + userName = p.userName, + userNickName = p.userNickName, + userId = p.userId, + ip = p.ip, + apiPath = p.apiPath, + beginTime = p.beginTime, + endTime = p.endTime, + opTime = p.opTime, + requestMethod = p.requestMethod, + //requestData = p.requestData, + //responseBodyData = p.responseBodyData, + agent = p.agent, + actionName = p.actionName, + actionDescription = p.actionDescription, + controllerName = p.controllerName, + controllerDescription = p.controllerDescription, + statusCode = p.statusCode, + createTime = p.createTime, + dataSources = p.dataSources, + + }).With(SqlWith.NoLock).ToPageListAsync(pageIndex, pageSize, totalCount); + } + else + { + page = await DbClient.Queryable() + .OrderByIF(orderByExpression != null, orderByExpression, orderByType) + .WhereIF(predicate != null, predicate).Select(p => new SysUserOperationLog + { + id = p.id, + userName = p.userName, + userNickName = p.userNickName, + userId = p.userId, + ip = p.ip, + apiPath = p.apiPath, + beginTime = p.beginTime, + endTime = p.endTime, + opTime = p.opTime, + requestMethod = p.requestMethod, + //requestData = p.requestData, + //responseBodyData = p.responseBodyData, + agent = p.agent, + actionName = p.actionName, + actionDescription = p.actionDescription, + controllerName = p.controllerName, + controllerDescription = p.controllerDescription, + statusCode = p.statusCode, + createTime = p.createTime, + dataSources = p.dataSources, + + }).ToPageListAsync(pageIndex, pageSize, totalCount); + } + var list = new PageList(page, pageIndex, pageSize, totalCount); + return list; + } + + #endregion + + } +} diff --git a/CoreCms.Net.Services/System/SysUserOperationLogServices.cs b/CoreCms.Net.Services/System/SysUserOperationLogServices.cs new file mode 100644 index 00000000..fb4b7efe --- /dev/null +++ b/CoreCms.Net.Services/System/SysUserOperationLogServices.cs @@ -0,0 +1,62 @@ +/*********************************************************************** + * Project: CoreCms + * ProjectName: 核心内容管理系统 + * Web: https://www.corecms.net + * Author: 大灰灰 + * Email: jianweie@163.com + * CreateTime: 2022/4/10 0:27:47 + * Description: 暂无 + ***********************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading.Tasks; +using CoreCms.Net.Configuration; +using CoreCms.Net.IRepository; +using CoreCms.Net.IRepository.UnitOfWork; +using CoreCms.Net.IServices; +using CoreCms.Net.Model.Entities; +using CoreCms.Net.Model.ViewModels.Basics; +using CoreCms.Net.Model.ViewModels.UI; +using SqlSugar; + + +namespace CoreCms.Net.Services +{ + /// + /// 用户操作日志 接口实现 + /// + public class SysUserOperationLogServices : BaseServices, ISysUserOperationLogServices + { + private readonly ISysUserOperationLogRepository _dal; + private readonly IUnitOfWork _unitOfWork; + + public SysUserOperationLogServices(IUnitOfWork unitOfWork, ISysUserOperationLogRepository dal) + { + this._dal = dal; + base.BaseDal = dal; + _unitOfWork = unitOfWork; + } + + #region 重写根据条件查询分页数据 + /// + /// 重写根据条件查询分页数据 + /// + /// 判断集合 + /// 排序方式 + /// 当前页面索引 + /// 分布大小 + /// + /// 是否使用WITH(NOLOCK) + /// + public new async Task> QueryPageAsync(Expression> predicate, + Expression> orderByExpression, OrderByType orderByType, int pageIndex = 1, + int pageSize = 20, bool blUseNoLock = false) + { + return await _dal.QueryPageAsync(predicate, orderByExpression, orderByType, pageIndex, pageSize, blUseNoLock); + } + #endregion + + } +} diff --git a/CoreCms.Net.Web.Admin/Controllers/Com/ToolsController.cs b/CoreCms.Net.Web.Admin/Controllers/Com/ToolsController.cs index 873db2c8..007437e4 100644 --- a/CoreCms.Net.Web.Admin/Controllers/Com/ToolsController.cs +++ b/CoreCms.Net.Web.Admin/Controllers/Com/ToolsController.cs @@ -345,7 +345,7 @@ namespace CoreCms.Net.Web.Admin.Controllers public AdminUiCallBack GetAllControllerAndActionByAssembly() { var jm = new AdminUiCallBack(); - var data = AdminsControllerPermission.GetAllControllerAndActionByAssembly(); + var data = AdminsControllerPermission.GetCacheCoreCmsControllerPermission(); jm.data = data.OrderBy(u => u.name).ToList(); jm.code = 0; jm.msg = "获取成功"; diff --git a/CoreCms.Net.Web.Admin/Controllers/System/SysUserOperationLogController.cs b/CoreCms.Net.Web.Admin/Controllers/System/SysUserOperationLogController.cs new file mode 100644 index 00000000..f654fd4a --- /dev/null +++ b/CoreCms.Net.Web.Admin/Controllers/System/SysUserOperationLogController.cs @@ -0,0 +1,350 @@ +/*********************************************************************** + * Project: CoreCms + * ProjectName: 核心内容管理系统 + * Web: https://www.corecms.net + * Author: 大灰灰 + * Email: jianweie@163.com + * CreateTime: 2022/4/10 0:27:47 + * Description: 暂无 + ***********************************************************************/ + + +using System; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; +using CoreCms.Net.Configuration; +using CoreCms.Net.Model.Entities; +using CoreCms.Net.Model.Entities.Expression; +using CoreCms.Net.Model.FromBody; +using CoreCms.Net.Model.ViewModels.UI; +using CoreCms.Net.Filter; +using CoreCms.Net.Loging; +using CoreCms.Net.IServices; +using CoreCms.Net.Utility.Helper; +using CoreCms.Net.Utility.Extensions; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using NPOI.HSSF.UserModel; +using SqlSugar; + +namespace CoreCms.Net.Web.Admin.Controllers +{ + /// + /// 用户操作日志 + /// + [Description("用户操作日志")] + [Route("api/[controller]/[action]")] + [ApiController] + [RequiredErrorForAdmin] + [Authorize] + public class SysUserOperationLogController : ControllerBase + { + private readonly IWebHostEnvironment _webHostEnvironment; + private readonly ISysUserOperationLogServices _sysUserOperationLogServices; + + /// + /// 构造函数 + /// + public SysUserOperationLogController(IWebHostEnvironment webHostEnvironment + ,ISysUserOperationLogServices sysUserOperationLogServices + ) + { + _webHostEnvironment = webHostEnvironment; + _sysUserOperationLogServices = sysUserOperationLogServices; + } + + #region 获取列表============================================================ + // POST: Api/SysUserOperationLog/GetPageList + /// + /// 获取列表 + /// + /// + [HttpPost] + [Description("获取列表")] + public async Task GetPageList() + { + var jm = new AdminUiCallBack(); + var pageCurrent = Request.Form["page"].FirstOrDefault().ObjectToInt(1); + var pageSize = Request.Form["limit"].FirstOrDefault().ObjectToInt(30); + var where = PredicateBuilder.True(); + //获取排序字段 + var orderField = Request.Form["orderField"].FirstOrDefault(); + + Expression> orderEx = orderField switch + { + "id" => p => p.id,"userName" => p => p.userName,"userNickName" => p => p.userNickName,"userId" => p => p.userId,"ip" => p => p.ip,"apiPath" => p => p.apiPath,"beginTime" => p => p.beginTime,"endTime" => p => p.endTime,"opTime" => p => p.opTime,"requestMethod" => p => p.requestMethod,"requestData" => p => p.requestData,"responseBodyData" => p => p.responseBodyData,"agent" => p => p.agent,"actionName" => p => p.actionName,"actionDescription" => p => p.actionDescription,"controllerName" => p => p.controllerName,"controllerDescription" => p => p.controllerDescription,"statusCode" => p => p.statusCode,"createTime" => p => p.createTime,"dataSources" => p => p.dataSources, + _ => p => p.id + }; + + //设置排序方式 + var orderDirection = Request.Form["orderDirection"].FirstOrDefault(); + var orderBy = orderDirection switch + { + "asc" => OrderByType.Asc, + "desc" => OrderByType.Desc, + _ => OrderByType.Desc + }; + //查询筛选 + + // int + var id = Request.Form["id"].FirstOrDefault().ObjectToInt(0); + if (id > 0) + { + where = where.And(p => p.id == id); + } + //用户登录账号 nvarchar + var userName = Request.Form["userName"].FirstOrDefault(); + if (!string.IsNullOrEmpty(userName)) + { + where = where.And(p => p.userName.Contains(userName)); + } + //用户登录昵称 nvarchar + var userNickName = Request.Form["userNickName"].FirstOrDefault(); + if (!string.IsNullOrEmpty(userNickName)) + { + where = where.And(p => p.userNickName.Contains(userNickName)); + } + //用户序列 nvarchar + var userId = Request.Form["userId"].FirstOrDefault().ObjectToInt(0); + if (userId > 0) + { + where = where.And(p => p.id == id); + } + //IP地址 nvarchar + var ip = Request.Form["ip"].FirstOrDefault(); + if (!string.IsNullOrEmpty(ip)) + { + where = where.And(p => p.ip.Contains(ip)); + } + //请求地址 nvarchar + var apiPath = Request.Form["apiPath"].FirstOrDefault(); + if (!string.IsNullOrEmpty(apiPath)) + { + where = where.And(p => p.apiPath.Contains(apiPath)); + } + //开始时间 datetime + var beginTime = Request.Form["beginTime"].FirstOrDefault(); + if (!string.IsNullOrEmpty(beginTime)) + { + if (beginTime.Contains("到")) + { + var dts = beginTime.Split("到"); + var dtStart = dts[0].Trim().ObjectToDate(); + where = where.And(p => p.beginTime > dtStart); + var dtEnd = dts[1].Trim().ObjectToDate(); + where = where.And(p => p.beginTime < dtEnd); + } + else + { + var dt = beginTime.ObjectToDate(); + where = where.And(p => p.beginTime > dt); + } + } + //结束时间 datetime + var endTime = Request.Form["endTime"].FirstOrDefault(); + if (!string.IsNullOrEmpty(endTime)) + { + if (endTime.Contains("到")) + { + var dts = endTime.Split("到"); + var dtStart = dts[0].Trim().ObjectToDate(); + where = where.And(p => p.endTime > dtStart); + var dtEnd = dts[1].Trim().ObjectToDate(); + where = where.And(p => p.endTime < dtEnd); + } + else + { + var dt = endTime.ObjectToDate(); + where = where.And(p => p.endTime > dt); + } + } + //耗时 nvarchar + var opTime = Request.Form["opTime"].FirstOrDefault(); + if (!string.IsNullOrEmpty(opTime)) + { + where = where.And(p => p.opTime.Contains(opTime)); + } + //请求方式 nvarchar + var requestMethod = Request.Form["requestMethod"].FirstOrDefault(); + if (!string.IsNullOrEmpty(requestMethod)) + { + where = where.And(p => p.requestMethod.Contains(requestMethod)); + } + //请求数据 nvarchar + var requestData = Request.Form["requestData"].FirstOrDefault(); + if (!string.IsNullOrEmpty(requestData)) + { + where = where.And(p => p.requestData.Contains(requestData)); + } + //返回数据 nvarchar + var responseBodyData = Request.Form["responseBodyData"].FirstOrDefault(); + if (!string.IsNullOrEmpty(responseBodyData)) + { + where = where.And(p => p.responseBodyData.Contains(responseBodyData)); + } + //代理渠道 nvarchar + var agent = Request.Form["agent"].FirstOrDefault(); + if (!string.IsNullOrEmpty(agent)) + { + where = where.And(p => p.agent.Contains(agent)); + } + //动作方法名称 nvarchar + var actionName = Request.Form["actionName"].FirstOrDefault(); + if (!string.IsNullOrEmpty(actionName)) + { + where = where.And(p => p.actionName.Contains(actionName)); + } + //动作方法描述 nvarchar + var actionDescription = Request.Form["actionDescription"].FirstOrDefault(); + if (!string.IsNullOrEmpty(actionDescription)) + { + where = where.And(p => p.actionDescription.Contains(actionDescription)); + } + //控制器名称 nvarchar + var controllerName = Request.Form["controllerName"].FirstOrDefault(); + if (!string.IsNullOrEmpty(controllerName)) + { + where = where.And(p => p.controllerName.Contains(controllerName)); + } + //控制器名称 nvarchar + var controllerDescription = Request.Form["controllerDescription"].FirstOrDefault(); + if (!string.IsNullOrEmpty(controllerDescription)) + { + where = where.And(p => p.controllerDescription.Contains(controllerDescription)); + } + //状态码 int + var statusCode = Request.Form["statusCode"].FirstOrDefault().ObjectToInt(0); + if (statusCode > 0) + { + where = where.And(p => p.statusCode == statusCode); + } + //创建时间 datetime + var createTime = Request.Form["createTime"].FirstOrDefault(); + if (!string.IsNullOrEmpty(createTime)) + { + if (createTime.Contains("到")) + { + var dts = createTime.Split("到"); + var dtStart = dts[0].Trim().ObjectToDate(); + where = where.And(p => p.createTime > dtStart); + var dtEnd = dts[1].Trim().ObjectToDate(); + where = where.And(p => p.createTime < dtEnd); + } + else + { + var dt = createTime.ObjectToDate(); + where = where.And(p => p.createTime > dt); + } + } + //数据来源 nvarchar + var dataSources = Request.Form["dataSources"].FirstOrDefault(); + if (!string.IsNullOrEmpty(dataSources)) + { + where = where.And(p => p.dataSources.Contains(dataSources)); + } + //获取数据 + var list = await _sysUserOperationLogServices.QueryPageAsync(where, orderEx, orderBy, pageCurrent, pageSize, true); + //返回数据 + jm.data = list; + jm.code = 0; + jm.count = list.TotalCount; + jm.msg = "数据调用成功!"; + return jm; + } + #endregion + + #region 首页数据============================================================ + // POST: Api/SysUserOperationLog/GetIndex + /// + /// 首页数据 + /// + /// + [HttpPost] + [Description("首页数据")] + public AdminUiCallBack GetIndex() + { + //返回数据 + var jm = new AdminUiCallBack { code = 0 }; + return jm; + } + #endregion + + #region 删除数据============================================================ + // POST: Api/SysUserOperationLog/DoDelete/10 + /// + /// 单选删除 + /// + /// + /// + [HttpPost] + [Description("单选删除")] + public async Task DoDelete([FromBody]FMIntId entity) + { + var jm = new AdminUiCallBack(); + + var model = await _sysUserOperationLogServices.ExistsAsync(p => p.id == entity.id, true); + if (!model) + { + jm.msg = GlobalConstVars.DataisNo; + return jm; + } + var bl = await _sysUserOperationLogServices.DeleteByIdAsync(entity.id); + jm.code = bl ? 0 : 1; + jm.msg = bl ? GlobalConstVars.DeleteSuccess : GlobalConstVars.DeleteFailure; + return jm; + } + #endregion + + #region 批量删除============================================================ + // POST: Api/SysUserOperationLog/DoBatchDelete/10,11,20 + /// + /// 批量删除 + /// + /// + /// + [HttpPost] + [Description("批量删除")] + public async Task DoBatchDelete([FromBody]FMArrayIntIds entity) + { + var jm = new AdminUiCallBack(); + + var bl = await _sysUserOperationLogServices.DeleteByIdsAsync(entity.id); + jm.code = bl ? 0 : 1; + jm.msg = bl ? GlobalConstVars.DeleteSuccess : GlobalConstVars.DeleteFailure; + return jm; + } + + #endregion + + #region 预览数据============================================================ + // POST: Api/SysUserOperationLog/GetDetails/10 + /// + /// 预览数据 + /// + /// + /// + [HttpPost] + [Description("预览数据")] + public async Task GetDetails([FromBody]FMIntId entity) + { + var jm = new AdminUiCallBack(); + + var model = await _sysUserOperationLogServices.QueryByIdAsync(entity.id, false); + if (model == null) + { + jm.msg = "不存在此信息"; + return jm; + } + jm.code = 0; + jm.data = model; + + return jm; + } + #endregion + + } +} diff --git a/CoreCms.Net.Web.Admin/Startup.cs b/CoreCms.Net.Web.Admin/Startup.cs index 30525909..b6138e72 100644 --- a/CoreCms.Net.Web.Admin/Startup.cs +++ b/CoreCms.Net.Web.Admin/Startup.cs @@ -174,7 +174,7 @@ namespace CoreCms.Net.Web.Admin // ¼뷵 (ע⿪ȨޣȻ޷д) app.UseRequestResponseLog(); // ûʼ¼(ŵ㣬Ȼ쳣ᱨΪܷ)(ע⿪ȨޣȻ޷д) - app.UseRecordAccessLogsMildd(); + app.UseRecordAccessLogsMildd(GlobalEnumVars.CoreShopSystemCategory.Admin.ToString()); // ¼ip (ע⿪ȨޣȻ޷д) app.UseIpLogMildd(); // signalr diff --git a/CoreCms.Net.Web.Admin/appsettings.json b/CoreCms.Net.Web.Admin/appsettings.json index 79cc340c..9aae3722 100644 --- a/CoreCms.Net.Web.Admin/appsettings.json +++ b/CoreCms.Net.Web.Admin/appsettings.json @@ -46,8 +46,10 @@ }, //记录用户方访问数据 "RecordAccessLogs": { - "Enabled": false, - "IgnoreApis": "/api/Home/GetNav,/api/Home/GetIds4Users" + "Enabled": true, //是否开启记录操作日志功能。 + "EnabledFileMode": false, //是否开启记录到文件功能。(影响效率,接口不建议开启) + "EnabledDbMode": true, //是否开启记录到数据库模式。(影响效率,接口不建议开启) + "IgnoreApis": "/api/tools/getuserinfo,/api/tools/getNavs,/api/CodeGenerator/CodeGenDown" //使用小写逗号分隔 }, //记录IP请求数据 "IPLog": { diff --git a/CoreCms.Net.Web.Admin/wwwroot/views/system/sysuseroperationlog/details.html b/CoreCms.Net.Web.Admin/wwwroot/views/system/sysuseroperationlog/details.html new file mode 100644 index 00000000..3d27b00c --- /dev/null +++ b/CoreCms.Net.Web.Admin/wwwroot/views/system/sysuseroperationlog/details.html @@ -0,0 +1,207 @@ + + \ No newline at end of file diff --git a/CoreCms.Net.Web.Admin/wwwroot/views/system/sysuseroperationlog/index.html b/CoreCms.Net.Web.Admin/wwwroot/views/system/sysuseroperationlog/index.html new file mode 100644 index 00000000..cef9d48f --- /dev/null +++ b/CoreCms.Net.Web.Admin/wwwroot/views/system/sysuseroperationlog/index.html @@ -0,0 +1,247 @@ +用户操作日志 + +
+
+ +
+
+ + + +
+
+
+ + + + + + + + + diff --git a/CoreCms.Net.Web.WebApi/Controllers/AgentController.cs b/CoreCms.Net.Web.WebApi/Controllers/AgentController.cs index 37bbbf17..e842b021 100644 --- a/CoreCms.Net.Web.WebApi/Controllers/AgentController.cs +++ b/CoreCms.Net.Web.WebApi/Controllers/AgentController.cs @@ -278,10 +278,10 @@ namespace CoreCms.Net.Web.WebApi.Controllers jm.status = true; jm.data = new { - count = first + second, + count = first + monthFirst, first, second, - monthCount = monthFirst + monthSecond, + monthCount = second + monthSecond, monthFirst, monthSecond }; diff --git a/CoreCms.Net.Web.WebApi/Startup.cs b/CoreCms.Net.Web.WebApi/Startup.cs index c83893a1..c6268658 100644 --- a/CoreCms.Net.Web.WebApi/Startup.cs +++ b/CoreCms.Net.Web.WebApi/Startup.cs @@ -181,7 +181,7 @@ namespace CoreCms.Net.Web.WebApi // ¼뷵 (ע⿪ȨޣȻ޷д) app.UseRequestResponseLog(); // ûʼ¼(ŵ㣬Ȼ쳣ᱨΪܷ)(ע⿪ȨޣȻ޷д) - app.UseRecordAccessLogsMildd(); + app.UseRecordAccessLogsMildd(GlobalEnumVars.CoreShopSystemCategory.Api.ToString()); // ¼ip (ע⿪ȨޣȻ޷д) app.UseIpLogMildd(); diff --git a/CoreCms.Net.Web.WebApi/appsettings.json b/CoreCms.Net.Web.WebApi/appsettings.json index 79cc340c..0a7c0094 100644 --- a/CoreCms.Net.Web.WebApi/appsettings.json +++ b/CoreCms.Net.Web.WebApi/appsettings.json @@ -46,8 +46,10 @@ }, //记录用户方访问数据 "RecordAccessLogs": { - "Enabled": false, - "IgnoreApis": "/api/Home/GetNav,/api/Home/GetIds4Users" + "Enabled": true, //是否开启记录操作日志功能。 + "EnabledFileMode": false, //是否开启记录到文件功能。(影响效率,接口不建议开启) + "EnabledDbMode": false, //是否开启记录到数据库模式。(影响效率,接口不建议开启) + "IgnoreApis": "/api/tools/getuserinfo,/api/tools/getNavs,/api/CodeGenerator/CodeGenDown" //使用小写逗号分隔 }, //记录IP请求数据 "IPLog": { diff --git a/数据库/MySql/20220410/1、创建表SysUserOperationLog.sql b/数据库/MySql/20220410/1、创建表SysUserOperationLog.sql new file mode 100644 index 00000000..f9eafbab --- /dev/null +++ b/数据库/MySql/20220410/1、创建表SysUserOperationLog.sql @@ -0,0 +1,52 @@ +/* + Navicat Premium Data Transfer + + Source Server : rm-wz92918pm46bsbc37mo.mysql.rds.aliyuncs.com + Source Server Type : MySQL + Source Server Version : 50732 + Source Host : rm-wz92918pm46bsbc37mo.mysql.rds.aliyuncs.com:3306 + Source Schema : coreshop + + Target Server Type : MySQL + Target Server Version : 50732 + File Encoding : 65001 + + Date: 10/04/2022 02:24:03 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for SysUserOperationLog +-- ---------------------------- +DROP TABLE IF EXISTS `SysUserOperationLog`; +CREATE TABLE `SysUserOperationLog` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '序列', + `userName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户登录账号', + `userNickName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户登录昵称', + `userId` int(11) NULL DEFAULT NULL COMMENT '用户序列', + `ip` varchar(150) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'IP地址', + `apiPath` varchar(150) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求地址', + `beginTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '开始时间', + `endTime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '结束时间', + `opTime` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '耗时', + `requestMethod` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求方式', + `requestData` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '请求数据', + `responseBodyData` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '返回数据', + `agent` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '代理渠道', + `actionName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '动作方法名称', + `actionDescription` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '动作方法描述', + `controllerName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '控制器名称', + `controllerDescription` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '控制器名称', + `statusCode` int(11) NULL DEFAULT NULL COMMENT '状态码', + `createTime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '创建时间', + `dataSources` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '数据来源', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of SysUserOperationLog +-- ---------------------------- + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/数据库/MySql/20220410/2、添加菜单.sql b/数据库/MySql/20220410/2、添加菜单.sql new file mode 100644 index 00000000..803d316b --- /dev/null +++ b/数据库/MySql/20220410/2、添加菜单.sql @@ -0,0 +1,24 @@ +/* + Navicat Premium Data Transfer + + Source Schema : coreshop + + Target Server Type : MySQL + Target Server Version : 50732 + File Encoding : 65001 + + Date: 10/04/2022 02:25:27 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; +-- ---------------------------- +-- Records of SysMenu +-- ---------------------------- +INSERT INTO `SysMenu` VALUES (1381, 111, 'sysuseroperationlog', '用户操作日志', '', 'system/sysuseroperationlog/index', '', 0, 400, '', NULL, NULL, 0, 0, '2022-04-10 02:06:29', NULL); +INSERT INTO `SysMenu` VALUES (1382, 111, 'GetPageList', '获取列表', NULL, NULL, '/Api/SysUserOperationLog/GetPageList', 1, 0, 'SysUserOperationLog:GetPageList', NULL, NULL, 0, 0, '2022-04-10 02:06:29', NULL); +INSERT INTO `SysMenu` VALUES (1383, 111, 'GetIndex', '首页数据', NULL, NULL, '/Api/SysUserOperationLog/GetIndex', 1, 1, 'SysUserOperationLog:GetIndex', NULL, NULL, 0, 0, '2022-04-10 02:06:29', NULL); +INSERT INTO `SysMenu` VALUES (1384, 111, 'DoDelete', '单选删除', NULL, NULL, '/Api/SysUserOperationLog/DoDelete', 1, 2, 'SysUserOperationLog:DoDelete', NULL, NULL, 0, 0, '2022-04-10 02:06:29', NULL); +INSERT INTO `SysMenu` VALUES (1385, 111, 'DoBatchDelete', '批量删除', NULL, NULL, '/Api/SysUserOperationLog/DoBatchDelete', 1, 3, 'SysUserOperationLog:DoBatchDelete', NULL, NULL, 0, 0, '2022-04-10 02:06:29', NULL); +INSERT INTO `SysMenu` VALUES (1386, 111, 'GetDetails', '预览数据', NULL, NULL, '/Api/SysUserOperationLog/GetDetails', 1, 4, 'SysUserOperationLog:GetDetails', NULL, NULL, 0, 0, '2022-04-10 02:06:29', NULL); +SET FOREIGN_KEY_CHECKS = 1; diff --git a/数据库/MySql/20220410/coreshop完整数据库脚本.rar b/数据库/MySql/20220410/coreshop完整数据库脚本.rar new file mode 100644 index 00000000..cf7ac07f Binary files /dev/null and b/数据库/MySql/20220410/coreshop完整数据库脚本.rar differ diff --git a/数据库/MySql/数据库更新日志.txt b/数据库/MySql/数据库更新日志.txt index b6d4b224..35375b68 100644 --- a/数据库/MySql/数据库更新日志.txt +++ b/数据库/MySql/数据库更新日志.txt @@ -1,3 +1,6 @@ +2022-04-10 +【新增】表【SysUserOperationLog】用户操作日志记录 + 2022-03-29 【新增】表【CoreCmsInvoice】 新增 【fileUrl】发票下载地址字段 diff --git a/数据库/SqlServer/20220410/1、创建数据库脚本.sql b/数据库/SqlServer/20220410/1、创建数据库脚本.sql new file mode 100644 index 00000000..bfb07aa9 --- /dev/null +++ b/数据库/SqlServer/20220410/1、创建数据库脚本.sql @@ -0,0 +1,105 @@ +/****** Object: Table [dbo].[SysUserOperationLog] Script Date: 2022/4/10 2:03:44 ******/ +SET ANSI_NULLS ON +GO + +SET QUOTED_IDENTIFIER ON +GO + +CREATE TABLE [dbo].[SysUserOperationLog]( + [id] [int] IDENTITY(1,1) NOT NULL, + [userName] [nvarchar](50) NULL, + [userNickName] [nvarchar](50) NULL, + [userId] [int] NOT NULL, + [ip] [nvarchar](150) NULL, + [apiPath] [nvarchar](150) NULL, + [beginTime] [datetime] NOT NULL, + [endTime] [datetime] NOT NULL, + [opTime] [nvarchar](50) NULL, + [requestMethod] [nvarchar](50) NULL, + [requestData] [nvarchar](max) NULL, + [responseBodyData] [nvarchar](max) NULL, + [agent] [nvarchar](1000) NULL, + [actionName] [nvarchar](50) NULL, + [actionDescription] [nvarchar](50) NULL, + [controllerName] [nvarchar](50) NULL, + [controllerDescription] [nvarchar](50) NULL, + [statusCode] [int] NOT NULL, + [createTime] [datetime] NOT NULL, + [dataSources] [nvarchar](50) NULL, + CONSTRAINT [PK_SysUserOperationLog] PRIMARY KEY CLUSTERED +( + [id] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] +GO + +ALTER TABLE [dbo].[SysUserOperationLog] ADD CONSTRAINT [DF_SysUserOperationLog_userId] DEFAULT ((0)) FOR [userId] +GO + +ALTER TABLE [dbo].[SysUserOperationLog] ADD CONSTRAINT [DF_SysUserOperationLog_statusCode] DEFAULT ((0)) FOR [statusCode] +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'id' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'û¼˺' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'userName' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'û¼dz' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'userNickName' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'û' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'userId' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'IPַ' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'ip' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'ַ' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'apiPath' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'ʼʱ' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'beginTime' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'ʱ' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'endTime' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'ʱ' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'opTime' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'ʽ' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'requestMethod' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'requestData' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'responseBodyData' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'agent' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'actionName' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'actionDescription' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'controllerName' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'controllerDescription' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'״̬' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'statusCode' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'ʱ' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'createTime' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'Դ' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog', @level2type=N'COLUMN',@level2name=N'dataSources' +GO + +EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'û־' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'SysUserOperationLog' +GO + + diff --git a/数据库/SqlServer/20220410/20220410完整数据库带演示商品.rar b/数据库/SqlServer/20220410/20220410完整数据库带演示商品.rar new file mode 100644 index 00000000..bd3388fb Binary files /dev/null and b/数据库/SqlServer/20220410/20220410完整数据库带演示商品.rar differ diff --git a/数据库/SqlServer/20220410/2、添加菜单脚本.sql b/数据库/SqlServer/20220410/2、添加菜单脚本.sql new file mode 100644 index 00000000..95551718 Binary files /dev/null and b/数据库/SqlServer/20220410/2、添加菜单脚本.sql differ diff --git a/数据库/SqlServer/数据库更新日志.txt b/数据库/SqlServer/数据库更新日志.txt index 0091b255..605569c5 100644 --- a/数据库/SqlServer/数据库更新日志.txt +++ b/数据库/SqlServer/数据库更新日志.txt @@ -1,3 +1,6 @@ +2022-04-10 +【新增】表【SysUserOperationLog】用户操作日志记录 + 2022-03-29 【新增】表【CoreCmsInvoice】 新增 【fileUrl】发票下载地址字段