操作日志功能完善

This commit is contained in:
橙子
2022-10-01 23:53:43 +08:00
parent 0b05d4d186
commit dd1aec3b60
28 changed files with 629 additions and 79 deletions

Binary file not shown.

View File

@@ -336,6 +336,14 @@
<param name="id"></param>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.OperationLogController.PageList(Yi.Framework.Model.Models.OperationLogEntity,Yi.Framework.Common.Models.PageParModel)">
<summary>
动态条件分页查询
</summary>
<param name="operationLog"></param>
<param name="page"></param>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.PostController.PageList(Yi.Framework.Model.Models.PostEntity,Yi.Framework.Common.Models.PageParModel)">
<summary>
动态条件分页查询
@@ -478,6 +486,13 @@
</summary>
<returns></returns>
</member>
<member name="M:Yi.Framework.ApiMicroservice.Controllers.TestController.LogTest(System.Collections.Generic.List{System.String})">
<summary>
操作日志测试
</summary>
<param name="par"></param>
<returns></returns>
</member>
<member name="T:Yi.Framework.ApiMicroservice.Controllers.UserController">
<summary>
用户管理

View File

@@ -0,0 +1,28 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Yi.Framework.Common.Models;
using Yi.Framework.Interface;
using Yi.Framework.Model.Models;
using Yi.Framework.Repository;
using Yi.Framework.WebCore;
using Yi.Framework.WebCore.AttributeExtend;
using Yi.Framework.WebCore.AuthorizationPolicy;
namespace Yi.Framework.ApiMicroservice.Controllers
{
[ApiController]
[Route("api/[controller]/[action]")]
public class LoginLogController : BaseCrudController<LoginLogEntity>
{
private ILoginLogService _iLoginLogService;
public LoginLogController(ILogger<LoginLogEntity> logger, ILoginLogService iLoginLogService) : base(logger, iLoginLogService)
{
_iLoginLogService = iLoginLogService;
}
}
}

View File

@@ -0,0 +1,41 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Yi.Framework.Common.Models;
using Yi.Framework.Interface;
using Yi.Framework.Model.Models;
using Yi.Framework.Repository;
using Yi.Framework.WebCore;
using Yi.Framework.WebCore.AttributeExtend;
using Yi.Framework.WebCore.AuthorizationPolicy;
namespace Yi.Framework.ApiMicroservice.Controllers
{
[ApiController]
[Route("api/[controller]/[action]")]
public class OperationLogController : BaseSimpleCrudController<OperationLogEntity>
{
private IOperationLogService _iOperationLogService;
public OperationLogController(ILogger<OperationLogEntity> logger, IOperationLogService iOperationLogService) : base(logger, iOperationLogService)
{
_iOperationLogService = iOperationLogService;
}
/// <summary>
/// 动态条件分页查询
/// </summary>
/// <param name="operationLog"></param>
/// <param name="page"></param>
/// <returns></returns>
[HttpGet]
public async Task<Result> PageList([FromQuery] OperationLogEntity operationLog, [FromQuery] PageParModel page)
{
return Result.Success().SetData(await _iOperationLogService.SelctPageList(operationLog, page));
}
}
}

View File

@@ -221,6 +221,7 @@ namespace Yi.Framework.ApiMicroservice.Controllers
return Result.Success();
}
/// <summary>
/// 清空数据库
/// </summary>
@@ -256,5 +257,17 @@ namespace Yi.Framework.ApiMicroservice.Controllers
var rep = _iUserService._repository;
return Result.Success().SetStatus(DbSeedExtend.Invoer(rep._Db));
}
/// <summary>
/// 操作日志测试
/// </summary>
/// <param name="par"></param>
/// <returns></returns>
[HttpPost]
[Log("测试模块", Common.Enum.OperEnum.Insert)]
public Result LogTest(List<string> par)
{
return Result.Success().SetData(par);
}
}
}

View File

@@ -163,6 +163,11 @@ app.UseStaticFiles();
//<2F><><EFBFBD><EFBFBD><EFBFBD>Թ<EFBFBD><D4B9>ʻ<EFBFBD>ע<EFBFBD><D7A2>
#endregion
app.UseLocalizerService();
#region
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>body
#endregion
app.UseHttpBodyService();
#region
//HttpsRedirectionע<6E><D7A2>
#endregion

View File

@@ -34,6 +34,9 @@
<None Update="Config\SwaggerDoc.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="ip2region.db">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="key.pem">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>

View File

@@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace Yi.Framework.Common.Enum
{
public enum OperationEnum
public enum OperEnum
{
Insert=1,
Update=2,

View File

@@ -7,6 +7,7 @@
<ItemGroup>
<PackageReference Include="EPPlus" Version="5.8.4" />
<PackageReference Include="Hei.Captcha" Version="0.3.0" />
<PackageReference Include="IPTools.Core" Version="1.6.0" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="6.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="SharpZipLib" Version="1.3.3" />

View File

@@ -38,7 +38,7 @@ namespace Yi.Framework.Core
claims.Add(new Claim(JwtRegisteredClaimNames.Nbf, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"));
claims.Add(new Claim(JwtRegisteredClaimNames.Exp, $"{new DateTimeOffset(DateTime.Now.AddMinutes(minutes)).ToUnixTimeSeconds()}"));
claims.Add(new Claim(JwtRegisteredClaimNames.Sid, user.Id.ToString()));
claims.Add(new Claim(JwtRegisteredClaimNames.Name, user.UserName));
claims.Add(new Claim("userName", user.UserName));
claims.Add(new Claim("deptId", user.DeptId.ToString()));
//-----------------------------以下从user的权限表中添加权限-----------------------例如:

View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Yi.Framework.Common.Models;
using Yi.Framework.Model.Models;
using Yi.Framework.Repository;
namespace Yi.Framework.Interface
{
public partial interface IOperationLogService:IBaseService<OperationLogEntity>
{
Task<PageModel<List<OperationLogEntity>>> SelctPageList(OperationLogEntity operationLog, PageParModel page);
}
}

View File

@@ -0,0 +1,9 @@
using Yi.Framework.Model.Models;
using Yi.Framework.Repository;
namespace Yi.Framework.Interface
{
public partial interface ILoginLogService:IBaseService<LoginLogEntity>
{
}
}

View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Yi.Framework.Common.Models;
using Yi.Framework.Model.Models;
using Yi.Framework.Repository;
namespace Yi.Framework.Interface
{
public partial interface IOperationLogService : IBaseService<OperationLogEntity>
{
}
}

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using SqlSugar;
namespace Yi.Framework.Model.Models
{
/// <summary>
/// 登入日志
///</summary>
[SugarTable("LoginLog")]
public partial class LoginLogEntity:IBaseModelEntity
{
public LoginLogEntity()
{
this.CreateTime = DateTime.Now;
}
[JsonConverter(typeof(ValueToStringConverter))]
[SugarColumn(ColumnName="Id" ,IsPrimaryKey = true )]
public long Id { get; set; }
/// <summary>
/// 登录用户
///</summary>
[SugarColumn(ColumnName="LoginUser" )]
public string LoginUser { get; set; }
/// <summary>
/// 登录地点
///</summary>
[SugarColumn(ColumnName="LoginLocation" )]
public string LoginLocation { get; set; }
/// <summary>
/// 登录Ip
///</summary>
[SugarColumn(ColumnName="LoginIp" )]
public string LoginIp { get; set; }
/// <summary>
/// 浏览器
///</summary>
[SugarColumn(ColumnName="Browser" )]
public string Browser { get; set; }
/// <summary>
/// 操作系统
///</summary>
[SugarColumn(ColumnName="Os" )]
public string Os { get; set; }
/// <summary>
/// 登录信息
///</summary>
[SugarColumn(ColumnName="LogMsg" )]
public string LogMsg { get; set; }
/// <summary>
/// 创建者
///</summary>
[SugarColumn(ColumnName="CreateUser" )]
public long? CreateUser { get; set; }
/// <summary>
/// 创建时间
///</summary>
[SugarColumn(ColumnName="CreateTime" )]
public DateTime? CreateTime { get; set; }
/// <summary>
/// 修改者
///</summary>
[SugarColumn(ColumnName="ModifyUser" )]
public long? ModifyUser { get; set; }
/// <summary>
/// 修改时间
///</summary>
[SugarColumn(ColumnName="ModifyTime" )]
public DateTime? ModifyTime { get; set; }
/// <summary>
/// 租户Id
///</summary>
[SugarColumn(ColumnName="TenantId" )]
public long? TenantId { get; set; }
/// <summary>
/// 排序字段
///</summary>
[SugarColumn(ColumnName="OrderNum" )]
public int? OrderNum { get; set; }
/// <summary>
/// 描述
///</summary>
[SugarColumn(ColumnName="Remark" )]
public string Remark { get; set; }
/// <summary>
/// 是否删除
///</summary>
[SugarColumn(ColumnName="IsDeleted" )]
public bool? IsDeleted { get; set; }
}
}

View File

@@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using SqlSugar;
namespace Yi.Framework.Model.Models
{
/// <summary>
/// 操作日志表
///</summary>
[SugarTable("OperationLog")]
public partial class OperationLogEntity:IBaseModelEntity
{
public OperationLogEntity()
{
this.CreateTime = DateTime.Now;
}
[JsonConverter(typeof(ValueToStringConverter))]
[SugarColumn(ColumnName="Id" ,IsPrimaryKey = true )]
public long Id { get; set; }
/// <summary>
/// 操作模块
///</summary>
[SugarColumn(ColumnName="Title" )]
public string Title { get; set; }
/// <summary>
/// 操作类型
///</summary>
[SugarColumn(ColumnName="OperType" )]
public int? OperType { get; set; }
/// <summary>
/// 请求方法
///</summary>
[SugarColumn(ColumnName="RequestMethod" )]
public string RequestMethod { get; set; }
/// <summary>
/// 操作人员
///</summary>
[SugarColumn(ColumnName="OperUser" )]
public string OperUser { get; set; }
/// <summary>
/// 操作Ip
///</summary>
[SugarColumn(ColumnName="OperIp" )]
public string OperIp { get; set; }
/// <summary>
/// 操作地点
///</summary>
[SugarColumn(ColumnName="OperLocation" )]
public string OperLocation { get; set; }
/// <summary>
/// 操作方法
///</summary>
[SugarColumn(ColumnName="Method" )]
public string Method { get; set; }
/// <summary>
/// 请求参数
///</summary>
[SugarColumn(ColumnName="RequestParam" )]
public string RequestParam { get; set; }
/// <summary>
/// 请求结果
///</summary>
[SugarColumn(ColumnName="RequestResult" )]
public string RequestResult { get; set; }
/// <summary>
/// 创建者
///</summary>
[SugarColumn(ColumnName="CreateUser" )]
public long? CreateUser { get; set; }
/// <summary>
/// 创建时间
///</summary>
[SugarColumn(ColumnName="CreateTime" )]
public DateTime? CreateTime { get; set; }
/// <summary>
/// 修改者
///</summary>
[SugarColumn(ColumnName="ModifyUser" )]
public long? ModifyUser { get; set; }
/// <summary>
/// 修改时间
///</summary>
[SugarColumn(ColumnName="ModifyTime" )]
public DateTime? ModifyTime { get; set; }
/// <summary>
/// 租户Id
///</summary>
[SugarColumn(ColumnName="TenantId" )]
public long? TenantId { get; set; }
/// <summary>
/// 排序字段
///</summary>
[SugarColumn(ColumnName="OrderNum" )]
public int? OrderNum { get; set; }
/// <summary>
/// 描述
///</summary>
[SugarColumn(ColumnName="Remark" )]
public string Remark { get; set; }
/// <summary>
/// 是否删除
///</summary>
[SugarColumn(ColumnName="IsDeleted" )]
public bool? IsDeleted { get; set; }
}
}

View File

@@ -335,7 +335,7 @@ namespace Yi.Framework.Model.SeedData
{
Id = SnowFlakeSingle.Instance.NextId(),
DictLabel = "成功",
DictValue = "0",
DictValue = "false",
DictType = "sys_common_status",
OrderNum = 100,
Remark = "正常状态",
@@ -346,7 +346,7 @@ namespace Yi.Framework.Model.SeedData
{
Id = SnowFlakeSingle.Instance.NextId(),
DictLabel = "失败",
DictValue = "1",
DictValue = "true",
DictType = "sys_common_status",
OrderNum = 99,
Remark = "失败状态",

View File

@@ -0,0 +1,29 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Yi.Framework.Common.Models;
using Yi.Framework.Interface;
using Yi.Framework.Model.Models;
using Yi.Framework.Repository;
namespace Yi.Framework.Service
{
public partial class OperationLogService : BaseService<OperationLogEntity>, IOperationLogService
{
public async Task<PageModel<List<OperationLogEntity>>> SelctPageList(OperationLogEntity operationLog, PageParModel page)
{
RefAsync<int> total = 0;
var data = await _repository._DbQueryable
.WhereIF(!string.IsNullOrEmpty(operationLog.Title), u => u.Title.Contains(operationLog.Title))
.WhereIF(!string.IsNullOrEmpty(operationLog.OperUser), u => u.OperUser.Contains(operationLog.OperUser))
.WhereIF(operationLog.OperType is not null, u => u.OperType==operationLog.OperType.GetHashCode())
.WhereIF(operationLog.IsDeleted.IsNotNull(), u => u.IsDeleted == operationLog.IsDeleted)
.OrderBy(u => u.OrderNum, OrderByType.Desc)
.ToPageListAsync(page.PageNum, page.PageSize, total);
return new PageModel<List<OperationLogEntity>>(data, total);
}
}
}

View File

@@ -0,0 +1,14 @@
using SqlSugar;
using Yi.Framework.Interface;
using Yi.Framework.Model.Models;
using Yi.Framework.Repository;
namespace Yi.Framework.Service
{
public partial class LoginLogService : BaseService<LoginLogEntity>, ILoginLogService
{
public LoginLogService(IRepository<LoginLogEntity> repository) : base(repository)
{
}
}
}

View File

@@ -0,0 +1,14 @@
using SqlSugar;
using Yi.Framework.Interface;
using Yi.Framework.Model.Models;
using Yi.Framework.Repository;
namespace Yi.Framework.Service
{
public partial class OperationLogService : BaseService<OperationLogEntity>, IOperationLogService
{
public OperationLogService(IRepository<OperationLogEntity> repository) : base(repository)
{
}
}
}

View File

@@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Mvc.Controllers;
using IPTools.Core;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using System;
@@ -6,36 +8,92 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Common.Helper;
using Yi.Framework.Common.Models;
using Yi.Framework.Interface;
using Yi.Framework.Model.Models;
namespace Yi.Framework.WebCore.AttributeExtend
{
public class GlobalLogAttribute : ActionFilterAttribute
{
private ILogger<GlobalLogAttribute> _logger;
private IOperationLogService _operationLogService;
//注入一个日志服务
public GlobalLogAttribute(ILogger<GlobalLogAttribute> logger)
public GlobalLogAttribute(ILogger<GlobalLogAttribute> logger, IOperationLogService operationLogService)
{
_logger = logger;
_operationLogService = operationLogService;
}
public override void OnResultExecuted(ResultExecutedContext context)
{
try
{
//查找标签,获取标签对象
//判断标签是在方法上
if (context.ActionDescriptor is not ControllerActionDescriptor controllerActionDescriptor) return;
//查找标签,获取标签对象
LogAttribute logAttribute = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true)
.FirstOrDefault(a => a.GetType().Equals(typeof(LogAttribute))) as LogAttribute;
if (logAttribute == null) return;
string controller = context.RouteData.Values["Controller"].ToString();
string action = context.RouteData.Values["Action"].ToString();
string ip = "127.0.0.1";
string ipData = "深圳";
//空对象直接返回
if (logAttribute is null) return;
////获取控制器名
//string controller = context.RouteData.Values["Controller"].ToString();
////获取方法名
//string action = context.RouteData.Values["Action"].ToString();
//获取Ip
string ip = context.HttpContext.GetClientIp();
//根据ip获取地址
//var ipTool = IpTool.Search(ip);
//string location = ipTool.Province + " " + ipTool.City;
//日志服务插入一条操作记录即可
var logEntity = new OperationLogEntity();
logEntity.OperIp = ip;
//logEntity.OperLocation = location;
logEntity.OperType = logAttribute.OperType.GetHashCode();
logEntity.Title = logAttribute.Title;
logEntity.RequestMethod = context.HttpContext.Request.Method;
logEntity.Method = context.HttpContext.Request.Path.Value;
logEntity.IsDeleted = false;
logEntity.OperUser= context.HttpContext.GetUserNameInfo();
if (logAttribute.IsSaveResponseData)
{
if (context.Result is ContentResult result && result.ContentType == "application/json")
{
logEntity.RequestResult = result.Content.Replace("\r\n", "").Trim();
}
if (context.Result is JsonResult result2)
{
logEntity.RequestResult = result2.Value?.ToString();
}
if (context.Result is ObjectResult result3)
{
logEntity.RequestResult = JsonHelper.ObjToStr(result3.Value);
}
}
if (logAttribute.IsSaveRequestData)
{
logEntity.RequestParam = context.HttpContext.GetRequestValue(logEntity.RequestMethod);
}
_operationLogService._repository.InsertReturnSnowflakeId(logEntity);
}
catch (Exception ex)
{
_logger.LogError(ex, $"操作日志错误:{ex.Message}");
_logger.LogError(ex, $"操作日志记录错误:{ex.Message}");
}
}

View File

@@ -13,11 +13,30 @@ namespace Yi.Framework.WebCore.AttributeExtend
[AttributeUsage(AttributeTargets.Method)]
public class LogAttribute : Attribute
{
private OperationEnum OperationType { get; set; }
/// <summary>
/// 操作类型
/// </summary>
public OperEnum OperType { get; set; }
public LogAttribute(OperationEnum operationType)
/// <summary>
/// 日志标题(模块)
/// </summary>
public string Title { get; set; }
/// <summary>
/// 是否保存请求数据
/// </summary>
public bool IsSaveRequestData { get; set; } = true;
/// <summary>
/// 是否保存返回数据
/// </summary>
public bool IsSaveResponseData { get; set; } = true;
public LogAttribute(string title, OperEnum operationType)
{
this.OperationType = operationType;
this.Title = title;
this.OperType = operationType;
}
}
}

View File

@@ -15,12 +15,12 @@ internal class JsonOptionsWritable<TOptions> : FileOptionsWritableBase<TOptions>
public override void Update(Action<TOptions> configuration)
{
JObject? jObject = JsonConvert.DeserializeObject<JObject>(File.ReadAllText(this.FileName));
JObject jObject = JsonConvert.DeserializeObject<JObject>(File.ReadAllText(this.FileName));
if (jObject != null)
{
TOptions option = this.Monitor.CurrentValue ?? new TOptions();
if (jObject.TryGetValue(this.Section, out JToken? jtoken))
if (jObject.TryGetValue(this.Section, out JToken jtoken))
{
option = JsonConvert.DeserializeObject<TOptions>(jtoken.ToString()) ?? new TOptions();
configuration?.Invoke(option);

View File

@@ -10,10 +10,11 @@ using System.Threading.Tasks;
using Yi.Framework.Model.Models;
using System.IdentityModel.Tokens.Jwt;
using System.IO;
using System.Text.RegularExpressions;
namespace Yi.Framework.WebCore
{
public static class CommonExtend
public static class HttpContextExtend
{
/// <summary>
/// 判断是否为异步请求
@@ -45,7 +46,7 @@ namespace Yi.Framework.WebCore
public static string GetUserNameInfo(this HttpContext httpContext)
{
var p = httpContext;
return httpContext.User.Claims.FirstOrDefault(u => u.Type == JwtRegisteredClaimNames.Name).Value;
return httpContext.User.Claims.FirstOrDefault(u => u.Type == "userName")?.Value;
}
/// <summary>
@@ -69,6 +70,8 @@ namespace Yi.Framework.WebCore
var p = httpContext;
return httpContext.User.Claims.FirstOrDefault(u => u.Type == "permission").Value;
}
/// <summary>
/// 基于HttpContext,当前鉴权方式解析,获取用户信息
/// 现在使用redis作为缓存不需要将菜单存放至jwt中了
@@ -96,18 +99,35 @@ namespace Yi.Framework.WebCore
};
}
/// <summary>
/// 设置文件下载名称
/// </summary>
/// <param name="httpContext"></param>
/// <param name="fileName"></param>
public static void FileInlineHandle(this HttpContext httpContext, string fileName)
{
string encodeFilename = System.Web.HttpUtility.UrlEncode(fileName, System.Text.Encoding.GetEncoding("UTF-8"));
httpContext.Response.Headers.Add("Content-Disposition", "inline;filename=" + encodeFilename);
}
/// <summary>
/// 设置文件附件名称
/// </summary>
/// <param name="httpContext"></param>
/// <param name="fileName"></param>
public static void FileAttachmentHandle(this HttpContext httpContext, string fileName)
{
string encodeFilename = System.Web.HttpUtility.UrlEncode(fileName, System.Text.Encoding.GetEncoding("UTF-8"));
httpContext.Response.Headers.Add("Content-Disposition", "attachment;filename=" + encodeFilename);
}
/// <summary>
/// 获取语言种类
/// </summary>
/// <param name="httpContext"></param>
/// <returns></returns>
public static string GetLanguage(this HttpContext httpContext)
{
string res = "zh-CN";
@@ -120,20 +140,13 @@ namespace Yi.Framework.WebCore
}
public static string GetBody(this HttpContext httpContext)
{
if (httpContext.Request.Body != null)
{
httpContext.Request.EnableBuffering();
httpContext.Request.Body.Position = 0;
StreamReader stream = new StreamReader(httpContext.Request.Body);
return stream.ReadToEndAsync().GetAwaiter().GetResult();
}
return "";
}
/// <summary>
/// 获取请求Body参数
/// </summary>
/// <param name="context"></param>
/// <param name="reqMethod"></param>
/// <returns></returns>
public static string GetRequestValue(this HttpContext context, string reqMethod)
{
string param;
@@ -151,5 +164,32 @@ namespace Yi.Framework.WebCore
}
return param;
}
/// <summary>
/// 获取客户端IP
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public static string GetClientIp(this HttpContext context)
{
if (context == null) return "";
var result = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
if (string.IsNullOrEmpty(result))
{
result = context.Connection.RemoteIpAddress?.ToString();
}
if (string.IsNullOrEmpty(result) || result.Contains("::1"))
result = "127.0.0.1";
result = result.Replace("::ffff:", "127.0.0.1");
//Ip规则效验
var regResult = Regex.IsMatch(result, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
result = regResult ? result : "127.0.0.1";
return result;
}
}
}

View File

@@ -0,0 +1,44 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.WebCore.MiddlewareExtend
{
public class HttpBodyMiddleware
{
private readonly RequestDelegate _next;
private ILogger<HttpBodyMiddleware> _logger;
public HttpBodyMiddleware(RequestDelegate next, ILogger<HttpBodyMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task Invoke(HttpContext context)
{
context.Request.EnableBuffering();
if (context.Request.Query.TryGetValue("access_token", out var token))
{
context.Request.Headers.Add("Authorization", $"Bearer {token}");
}
await _next(context);
}
}
public static class HttpBodyExtend
{
public static IApplicationBuilder UseHttpBodyService(this IApplicationBuilder builder)
{
return builder.UseMiddleware<HttpBodyMiddleware>();
}
}
}

View File

@@ -3,7 +3,7 @@ import request from '@/utils/request'
// 查询操作日志列表
export function list(query) {
return request({
url: '/monitor/operlog/list',
url: '/operationLog/pageList',
method: 'get',
params: query
})
@@ -12,15 +12,16 @@ export function list(query) {
// 删除操作日志
export function delOperlog(operId) {
return request({
url: '/monitor/operlog/' + operId,
method: 'delete'
url: '/operationLog/delList',
method: 'delete',
data:"string"==typeof(operId)?[operId]:operId
})
}
// 清空操作日志
export function cleanOperlog() {
return request({
url: '/monitor/operlog/clean',
url: '/operationLog/clear',
method: 'delete'
})
}

View File

@@ -10,18 +10,18 @@
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="操作人员" prop="operName">
<el-form-item label="操作人员" prop="operUser">
<el-input
v-model="queryParams.operName"
v-model="queryParams.operUser"
placeholder="请输入操作人员"
clearable
style="width: 240px;"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="类型" prop="businessType">
<el-form-item label="类型" prop="operType">
<el-select
v-model="queryParams.businessType"
v-model="queryParams.operType"
placeholder="操作类型"
clearable
style="width: 240px"
@@ -34,21 +34,12 @@
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="操作状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in sys_common_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="isDeleted">
<el-select v-model="queryParams.isDeleted" placeholder="日志状态" clearable style="width: 240px">
<el-option v-for="dict in sys_common_status" :key="dict.value" :label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="操作时间" style="width: 308px">
<el-date-picker
v-model="dateRange"
@@ -99,24 +90,24 @@
<el-table ref="operlogRef" v-loading="loading" :data="operlogList" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="日志编号" align="center" prop="operId" />
<el-table-column label="日志编号" align="center" prop="id" />
<el-table-column label="系统模块" align="center" prop="title" />
<el-table-column label="操作类型" align="center" prop="businessType">
<el-table-column label="操作类型" align="center" prop="operType">
<template #default="scope">
<dict-tag :options="sys_oper_type" :value="scope.row.businessType" />
<dict-tag :options="sys_oper_type" :value="scope.row.operType" />
</template>
</el-table-column>
<el-table-column label="请求方式" align="center" prop="requestMethod" />
<el-table-column label="操作人员" align="center" prop="operName" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" width="100" />
<el-table-column label="操作人员" align="center" prop="operUser" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" width="100" />
<el-table-column label="主机" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" />
<el-table-column label="操作状态" align="center" prop="status">
<el-table-column label="操作状态" align="center" prop="isDeleted">
<template #default="scope">
<dict-tag :options="sys_common_status" :value="scope.row.status" />
<dict-tag :options="sys_common_status" :value="scope.row.isDeleted" />
</template>
</el-table-column>
<el-table-column label="操作日期" align="center" prop="operTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180">
<el-table-column label="操作日期" align="center" prop="createTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.operTime) }}</span>
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
@@ -147,32 +138,32 @@
<el-form-item label="操作模块:">{{ form.title }} / {{ typeFormat(form) }}</el-form-item>
<el-form-item
label="登录信息:"
>{{ form.operName }} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item>
>{{ form.operUser }} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="请求地址:">{{ form.operUrl }}</el-form-item>
<el-form-item label="请求地址:">{{ form.method }}</el-form-item>
<el-form-item label="请求方式:">{{ form.requestMethod }}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="操作方法:">{{ form.method }}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="请求参数:">{{ form.operParam }}</el-form-item>
<el-form-item label="请求参数:">{{ form.requestParam }}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item>
<el-form-item label="返回参数:">{{ form.requestResult }}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="操作状态:">
<div v-if="form.status === 0">正常</div>
<div v-else-if="form.status === 1">失败</div>
<div v-if="form.isDeleted === false">正常</div>
<div v-else-if="form.isDeleted === true">失败</div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="操作时间:">{{ parseTime(form.operTime) }}</el-form-item>
<el-form-item label="操作时间:">{{ parseTime(form.createTime) }}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="异常信息:" v-if="form.status === 1">{{ form.errorMsg }}</el-form-item>
<el-form-item label="异常信息:" v-if="form.isDeleted === 1">{{ form.errorMsg }}</el-form-item>
</el-col>
</el-row>
</el-form>
@@ -209,9 +200,9 @@ const data = reactive({
pageNum: 1,
pageSize: 10,
title: undefined,
operName: undefined,
businessType: undefined,
status: undefined
operUser: undefined,
operType: undefined,
isDeleted: undefined
}
});
@@ -221,8 +212,8 @@ const { queryParams, form } = toRefs(data);
function getList() {
loading.value = true;
list(proxy.addDateRange(queryParams.value, dateRange.value)).then(response => {
operlogList.value = response.rows;
total.value = response.total;
operlogList.value = response.data.data;
total.value = response.data.total;
loading.value = false;
});
}
@@ -244,7 +235,7 @@ function resetQuery() {
}
/** 多选框选中数据 */
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.operId);
ids.value = selection.map(item => item.id);
multiple.value = !selection.length;
}
/** 排序触发事件 */
@@ -260,7 +251,7 @@ function handleView(row) {
}
/** 删除按钮操作 */
function handleDelete(row) {
const operIds = row.operId || ids.value;
const operIds = row.id || ids.value;
proxy.$modal.confirm('是否确认删除日志编号为"' + operIds + '"的数据项?').then(function () {
return delOperlog(operIds);
}).then(() => {