From b37c72ff151e53c466238d75bef14a4a60c9800f Mon Sep 17 00:00:00 2001 From: CGW406 <13565294+cgw406@user.noreply.gitee.com> Date: Fri, 24 Apr 2026 13:10:04 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E7=94=A8=E6=88=B7=E7=AE=A1=E7=90=86):=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=94=A8=E6=88=B7=E6=9C=80=E5=90=8E=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E6=97=B6=E9=97=B4=E8=AE=B0=E5=BD=95=E5=92=8C=E7=AD=9B?= =?UTF-8?q?=E9=80=89=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在用户管理功能中增加最后登录时间字段,支持记录和展示用户最后登录时间 添加按最后登录时间范围筛选用户的功能 修改登录逻辑以更新用户的最后登录时间 --- .../controller/OrganizationController.java | 7 ++++-- .../infra/service/DefaultSessionService.java | 11 +++++++++- .../tech/wetech/admin3/sys/model/User.java | 11 ++++++++++ .../admin3/sys/repository/UserRepository.java | 5 ++++- .../admin3/sys/service/UserService.java | 6 ++--- .../admin3/sys/service/dto/OrgUserDTO.java | 3 ++- admin3-ui/src/api/organization.ts | 2 +- admin3-ui/src/views/user-list.vue | 22 +++++++++++++++++++ 8 files changed, 58 insertions(+), 9 deletions(-) diff --git a/admin3-server/src/main/java/tech/wetech/admin3/controller/OrganizationController.java b/admin3-server/src/main/java/tech/wetech/admin3/controller/OrganizationController.java index 634caccc..aaa321f5 100644 --- a/admin3-server/src/main/java/tech/wetech/admin3/controller/OrganizationController.java +++ b/admin3-server/src/main/java/tech/wetech/admin3/controller/OrganizationController.java @@ -5,6 +5,8 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.web.SortDefault; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -19,6 +21,7 @@ import tech.wetech.admin3.sys.service.dto.OrgUserDTO; import tech.wetech.admin3.sys.service.dto.PageDTO; +import java.time.LocalDateTime; import java.util.List; import static tech.wetech.admin3.sys.model.Organization.Type; @@ -47,9 +50,9 @@ public ResponseEntity> findOrgTree(Long parentId) { @RequiresPermissions("user:view") @GetMapping("/{organizationId}/users") - public ResponseEntity> findOrgUsers(Pageable pageable, @RequestParam(required = false) String username, @RequestParam(required = false) User.State state, @PathVariable Long organizationId) { + public ResponseEntity> findOrgUsers(@SortDefault(sort = "lastLoginTime", direction = Sort.Direction.DESC) Pageable pageable, @RequestParam(required = false) String username, @RequestParam(required = false) User.State state, @RequestParam(required = false) LocalDateTime lastLoginTimeStart, @RequestParam(required = false) LocalDateTime lastLoginTimeEnd, @PathVariable Long organizationId) { Organization organization = organizationService.findOrganization(organizationId); - return ResponseEntity.ok(userService.findOrgUsers(pageable, username, state, organization)); + return ResponseEntity.ok(userService.findOrgUsers(pageable, username, state, organization, lastLoginTimeStart, lastLoginTimeEnd)); } @RequiresPermissions("organization:create") diff --git a/admin3-server/src/main/java/tech/wetech/admin3/infra/service/DefaultSessionService.java b/admin3-server/src/main/java/tech/wetech/admin3/infra/service/DefaultSessionService.java index 59798d41..bc1105ba 100644 --- a/admin3-server/src/main/java/tech/wetech/admin3/infra/service/DefaultSessionService.java +++ b/admin3-server/src/main/java/tech/wetech/admin3/infra/service/DefaultSessionService.java @@ -2,6 +2,7 @@ import jakarta.servlet.http.HttpServletRequest; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import tech.wetech.admin3.common.CommonResultStatus; @@ -14,9 +15,11 @@ import tech.wetech.admin3.sys.model.User; import tech.wetech.admin3.sys.model.UserCredential; import tech.wetech.admin3.sys.repository.UserCredentialRepository; +import tech.wetech.admin3.sys.repository.UserRepository; import tech.wetech.admin3.sys.service.SessionService; import tech.wetech.admin3.sys.service.dto.UserinfoDTO; +import java.time.LocalDateTime; import java.util.UUID; import static tech.wetech.admin3.sys.model.UserCredential.IdentityType.PASSWORD; @@ -29,15 +32,19 @@ public class DefaultSessionService implements SessionService { private final UserCredentialRepository userCredentialRepository; + private final UserRepository userRepository; + private final SessionManager sessionManager; - public DefaultSessionService(UserCredentialRepository userCredentialRepository, SessionManager sessionManager) { + public DefaultSessionService(UserCredentialRepository userCredentialRepository, UserRepository userRepository, SessionManager sessionManager) { this.userCredentialRepository = userCredentialRepository; + this.userRepository = userRepository; this.sessionManager = sessionManager; } @Override + @Transactional public UserinfoDTO login(String username, String password) { UserCredential credential = userCredentialRepository.findCredential(username, PASSWORD) .orElseThrow(() -> new UserException(CommonResultStatus.UNAUTHORIZED, "密码不正确")); @@ -46,6 +53,8 @@ public UserinfoDTO login(String username, String password) { if (user.isLocked()) { throw new UserException(CommonResultStatus.UNAUTHORIZED, "用户已经停用,请与管理员联系"); } + user.setLastLoginTime(LocalDateTime.now()); + userRepository.save(user); String token = UUID.randomUUID().toString().replace("-", ""); UserinfoDTO userinfo = new UserinfoDTO(token, user.getId(), user.getUsername(), user.getAvatar(), new UserinfoDTO.Credential(credential.getIdentifier(), credential.getIdentityType()), user.findPermissions()); sessionManager.store(token, credential, userinfo); diff --git a/admin3-server/src/main/java/tech/wetech/admin3/sys/model/User.java b/admin3-server/src/main/java/tech/wetech/admin3/sys/model/User.java index a44960dc..92c27830 100644 --- a/admin3-server/src/main/java/tech/wetech/admin3/sys/model/User.java +++ b/admin3-server/src/main/java/tech/wetech/admin3/sys/model/User.java @@ -32,6 +32,9 @@ public class User extends BaseEntity { @Column private LocalDateTime createdTime; + @Column + private LocalDateTime lastLoginTime; + @ManyToMany(fetch = LAZY, cascade = CascadeType.DETACH) @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), @@ -126,6 +129,14 @@ public void setCreatedTime(LocalDateTime createdTime) { this.createdTime = createdTime; } + public LocalDateTime getLastLoginTime() { + return lastLoginTime; + } + + public void setLastLoginTime(LocalDateTime lastLoginTime) { + this.lastLoginTime = lastLoginTime; + } + public Set getRoles() { return roles; } diff --git a/admin3-server/src/main/java/tech/wetech/admin3/sys/repository/UserRepository.java b/admin3-server/src/main/java/tech/wetech/admin3/sys/repository/UserRepository.java index 16ec30e2..8de83354 100644 --- a/admin3-server/src/main/java/tech/wetech/admin3/sys/repository/UserRepository.java +++ b/admin3-server/src/main/java/tech/wetech/admin3/sys/repository/UserRepository.java @@ -8,6 +8,7 @@ import tech.wetech.admin3.sys.model.Organization; import tech.wetech.admin3.sys.model.User; +import java.time.LocalDateTime; import java.util.Set; /** @@ -23,8 +24,10 @@ public interface UserRepository extends JpaRepository { from User user where (user.organization=:organization or user.organization.parentIds like concat(:orgParentIds, '%')) and (:username is null or user.username=:username) and (:state is null or user.state=:state) + and (:lastLoginTimeStart is null or user.lastLoginTime >= :lastLoginTimeStart) + and (:lastLoginTimeEnd is null or user.lastLoginTime <= :lastLoginTimeEnd) """) - Page findOrgUsers(Pageable pageable, String username, User.State state, Organization organization, String orgParentIds); + Page findOrgUsers(Pageable pageable, String username, User.State state, Organization organization, String orgParentIds, LocalDateTime lastLoginTimeStart, LocalDateTime lastLoginTimeEnd); @Query("select count(user.id) from User user where user.organization=:organization or user.organization.parentIds like concat(:orgParentIds, '%')") long countOrgUsers(Organization organization, String orgParentIds); diff --git a/admin3-server/src/main/java/tech/wetech/admin3/sys/service/UserService.java b/admin3-server/src/main/java/tech/wetech/admin3/sys/service/UserService.java index f7220776..f2d9f9a1 100644 --- a/admin3-server/src/main/java/tech/wetech/admin3/sys/service/UserService.java +++ b/admin3-server/src/main/java/tech/wetech/admin3/sys/service/UserService.java @@ -59,10 +59,10 @@ public User findUserById(Long userId) { .orElseThrow(() -> new BusinessException(RECORD_NOT_EXIST)); } - public PageDTO findOrgUsers(Pageable pageable, String username, User.State state, Organization organization) { - Page page = userRepository.findOrgUsers(pageable, username, state, organization, organization.makeSelfAsParentIds()); + public PageDTO findOrgUsers(Pageable pageable, String username, User.State state, Organization organization, LocalDateTime lastLoginTimeStart, LocalDateTime lastLoginTimeEnd) { + Page page = userRepository.findOrgUsers(pageable, username, state, organization, organization.makeSelfAsParentIds(), lastLoginTimeStart, lastLoginTimeEnd); return new PageDTO<>(page.getContent().stream().map(u -> - new OrgUserDTO(u.getId(), u.getUsername(), u.getAvatar(), u.getGender(), u.getState(), u.getOrgFullName(), u.getCreatedTime())) + new OrgUserDTO(u.getId(), u.getUsername(), u.getAvatar(), u.getGender(), u.getState(), u.getOrgFullName(), u.getCreatedTime(), u.getLastLoginTime())) .collect(Collectors.toList()), page.getTotalElements()); } diff --git a/admin3-server/src/main/java/tech/wetech/admin3/sys/service/dto/OrgUserDTO.java b/admin3-server/src/main/java/tech/wetech/admin3/sys/service/dto/OrgUserDTO.java index a2b157c6..0cbb6d57 100644 --- a/admin3-server/src/main/java/tech/wetech/admin3/sys/service/dto/OrgUserDTO.java +++ b/admin3-server/src/main/java/tech/wetech/admin3/sys/service/dto/OrgUserDTO.java @@ -13,5 +13,6 @@ public record OrgUserDTO(Long id, User.Gender gender, User.State state, String orgFullName, - LocalDateTime createdTime) { + LocalDateTime createdTime, + LocalDateTime lastLoginTime) { } diff --git a/admin3-ui/src/api/organization.ts b/admin3-ui/src/api/organization.ts index 298c5891..ed704a9f 100644 --- a/admin3-ui/src/api/organization.ts +++ b/admin3-ui/src/api/organization.ts @@ -9,7 +9,7 @@ export function getOrganizationTree(params: { parentId: number }) { }); } -export function getOrganizationUserList(organizationId: number, data: { page: number; size: number; username?: string, state?: string, roleId?: number }) { +export function getOrganizationUserList(organizationId: number, data: { page: number; size: number; username?: string, state?: string, roleId?: number, lastLoginTimeStart?: string, lastLoginTimeEnd?: string }) { return request({ url: `${BASE_URI}/organizations/${organizationId}/users`, method: 'get', diff --git a/admin3-ui/src/views/user-list.vue b/admin3-ui/src/views/user-list.vue index 0e349b6e..03c291b5 100644 --- a/admin3-ui/src/views/user-list.vue +++ b/admin3-ui/src/views/user-list.vue @@ -58,6 +58,22 @@ + + 搜索 新增 @@ -94,6 +110,7 @@ +