@@ -35,19 +35,61 @@ public async Task<ApiResult> Login([FromBody] LoginRequest req)
3535 . FirstOrDefaultAsync ( u => u . UserName == req . UserName
3636 && u . Password == pwdMd5
3737 && u . Deleted == 0 ) ;
38+
39+ // 记录登录日志
40+ var loginIp = HttpContext . Connection ? . RemoteIpAddress ? . ToString ( ) ;
41+ var loginUA = HttpContext . Request . Headers . UserAgent . ToString ( ) ;
42+
3843 if ( user == null )
44+ {
45+ // 记录失败日志
46+ _db . LoginLogs . Add ( new LoginLogEntity
47+ {
48+ UserName = req . UserName , LoginType = "login" , Result = "fail" ,
49+ IpAddress = loginIp , UserAgent = loginUA ,
50+ Deleted = 0 , CreatedAt = DateTime . Now . ToString ( "o" )
51+ } ) ;
52+ await _db . SaveChangesAsync ( ) ;
3953 return ApiResult . Fail ( "用户名或密码错误" , 401 ) ;
54+ }
4055
4156 // 检查租户是否禁用或过期
4257 if ( user . TenantId . HasValue )
4358 {
4459 var tenant = await _db . Tenants . FindAsync ( user . TenantId . Value ) ;
4560 if ( tenant == null || tenant . Deleted == 1 || tenant . Status == 0 )
61+ {
62+ _db . LoginLogs . Add ( new LoginLogEntity
63+ {
64+ UserId = user . Id , UserName = user . UserName , LoginType = "login" , Result = "fail" ,
65+ IpAddress = loginIp , UserAgent = loginUA , TenantId = user . TenantId ,
66+ Deleted = 0 , CreatedAt = DateTime . Now . ToString ( "o" )
67+ } ) ;
68+ await _db . SaveChangesAsync ( ) ;
4669 return ApiResult . Fail ( "租户已被禁用,无法登录" , 403 ) ;
70+ }
4771 if ( tenant . ExpiredAt . HasValue && tenant . ExpiredAt . Value < DateTime . Now )
72+ {
73+ _db . LoginLogs . Add ( new LoginLogEntity
74+ {
75+ UserId = user . Id , UserName = user . UserName , LoginType = "login" , Result = "fail" ,
76+ IpAddress = loginIp , UserAgent = loginUA , TenantId = user . TenantId ,
77+ Deleted = 0 , CreatedAt = DateTime . Now . ToString ( "o" )
78+ } ) ;
79+ await _db . SaveChangesAsync ( ) ;
4880 return ApiResult . Fail ( "租户已过期,无法登录" , 403 ) ;
81+ }
4982 }
5083
84+ // 记录成功登录日志
85+ _db . LoginLogs . Add ( new LoginLogEntity
86+ {
87+ UserId = user . Id , UserName = user . UserName , LoginType = "login" , Result = "success" ,
88+ IpAddress = loginIp , UserAgent = loginUA , TenantId = user . TenantId ,
89+ Deleted = 0 , CreatedAt = DateTime . Now . ToString ( "o" )
90+ } ) ;
91+ await _db . SaveChangesAsync ( ) ;
92+
5193 var tokenStr = _jwtService . GenerateToken ( user ) ;
5294
5395 // 查询菜单权限(角色权限 ∩ 租户权限)
@@ -266,4 +308,30 @@ public async Task<ApiResult> Delete(long id)
266308 await _db . SaveChangesAsync ( ) ;
267309 return ApiResult . Success ( ) ;
268310 }
311+
312+ /// <summary>登录日志分页列表</summary>
313+ [ HttpPost ( "login-log/page" ) , Authorize ]
314+ public async Task < ApiResult > LoginLogPage ( [ FromBody ] PageRequest req )
315+ {
316+ if ( ! _tenant . IsSuperAdmin )
317+ return ApiResult . Fail ( "仅超级管理员可查看" , 403 ) ;
318+
319+ var query = _db . LoginLogs . Where ( l => l . Deleted == 0 ) ;
320+ if ( ! string . IsNullOrEmpty ( req . Keyword ) )
321+ query = query . Where ( l => ( l . UserName != null && l . UserName . Contains ( req . Keyword ) )
322+ || ( l . IpAddress != null && l . IpAddress . Contains ( req . Keyword ) ) ) ;
323+
324+ var total = await query . CountAsync ( ) ;
325+ var records = await query . OrderByDescending ( l => l . Id )
326+ . Skip ( ( req . PageNum - 1 ) * req . PageSize )
327+ . Take ( req . PageSize )
328+ . Select ( l => new
329+ {
330+ l . Id , l . UserId , l . UserName , l . LoginType , l . Result ,
331+ l . IpAddress , l . TenantId , l . CreatedAt
332+ } )
333+ . ToListAsync ( ) ;
334+
335+ return ApiResult . Success ( new { total , records } ) ;
336+ }
269337}
0 commit comments