操作日志功能完善
This commit is contained in:
Binary file not shown.
@@ -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>
|
||||
用户管理
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
BIN
Yi.Framework.Net6/Yi.Framework.ApiMicroservice/ip2region.db
Normal file
BIN
Yi.Framework.Net6/Yi.Framework.ApiMicroservice/ip2region.db
Normal file
Binary file not shown.
Binary file not shown.
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Yi.Framework.Common.Enum
|
||||
{
|
||||
public enum OperationEnum
|
||||
public enum OperEnum
|
||||
{
|
||||
Insert=1,
|
||||
Update=2,
|
||||
@@ -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" />
|
||||
|
||||
@@ -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的权限表中添加权限-----------------------例如:
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Yi.Framework.Model.Models;
|
||||
using Yi.Framework.Repository;
|
||||
|
||||
namespace Yi.Framework.Interface
|
||||
{
|
||||
public partial interface ILoginLogService:IBaseService<LoginLogEntity>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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 = "失败状态",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
Reference in New Issue
Block a user