【7.6.0】【sys】【loginuser】更新查询在线用户列表接口

pull/57/head
fengshuonan 2023-07-02 13:56:55 +08:00
parent e883c39ebf
commit 40b8ef8fad
7 changed files with 345 additions and 5 deletions

View File

@ -24,6 +24,7 @@
*/ */
package cn.stylefeng.roses.kernel.sys.api; package cn.stylefeng.roses.kernel.sys.api;
import cn.stylefeng.roses.kernel.sys.api.pojo.user.OnlineUserItem;
import cn.stylefeng.roses.kernel.sys.api.pojo.user.SimpleUserDTO; import cn.stylefeng.roses.kernel.sys.api.pojo.user.SimpleUserDTO;
import cn.stylefeng.roses.kernel.sys.api.pojo.user.UserValidateDTO; import cn.stylefeng.roses.kernel.sys.api.pojo.user.UserValidateDTO;
@ -94,4 +95,26 @@ public interface SysUserServiceApi {
*/ */
Boolean userExist(Long userId); Boolean userExist(Long userId);
/**
*
* <p>
* 线
*
* @author fengshuonan
* @since 2023/7/2 13:22
*/
OnlineUserItem getUserNameAccountInfo(Long userId);
/**
*
* <p>
* 线
*
* @param onlineUserItems id
* @param searchText
* @author fengshuonan
* @since 2023/7/2 13:36
*/
List<OnlineUserItem> getUserNameAccountInfoListByCondition(List<OnlineUserItem> onlineUserItems, String searchText);
} }

View File

@ -26,7 +26,12 @@ public enum UserExceptionEnum implements AbstractExceptionEnum {
/** /**
* *
*/ */
RESET_PASSWORD_ERROR(RuleConstants.USER_OPERATION_ERROR_TYPE_CODE + "10003", "无法操作,只有超级管理员可以重置密码!"); RESET_PASSWORD_ERROR(RuleConstants.USER_OPERATION_ERROR_TYPE_CODE + "10003", "无法操作,只有超级管理员可以重置密码!"),
/**
* 线
*/
KICK_OFF_ERROR(RuleConstants.USER_OPERATION_ERROR_TYPE_CODE + "10004", "无法操作,只有超级管理员可以踢下线用户");
/** /**
* *

View File

@ -0,0 +1,72 @@
package cn.stylefeng.roses.kernel.sys.api.pojo.user;
import cn.stylefeng.roses.kernel.rule.annotation.ChineseDescription;
import cn.stylefeng.roses.kernel.rule.pojo.request.BaseRequest;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import java.util.Date;
/**
* 线
*
* @author fengshuonan
* @since 2023/7/2 11:30
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class OnlineUserItem extends BaseRequest {
/**
* id
*/
@ChineseDescription("用户主键id")
private Long userId;
/**
* token
*/
@ChineseDescription("用户token")
@NotBlank(message = "用户token不能为空", groups = offlineUser.class)
private String token;
/**
*
*/
@ChineseDescription("真实姓名")
private String realName;
/**
*
*/
@ChineseDescription("账号")
private String account;
/**
* ip
*/
@ChineseDescription("登录时的ip")
private String loginIp;
/**
*
*/
@ChineseDescription("登录时间")
private Date loginTime;
/**
* 线token
*/
public @interface offlineUser {
}
public OnlineUserItem() {
}
public OnlineUserItem(Long userId, String realName, String account) {
this.userId = userId;
this.realName = realName;
this.account = account;
}
}

View File

@ -21,6 +21,7 @@ import cn.stylefeng.roses.kernel.sys.api.constants.SysConstants;
import cn.stylefeng.roses.kernel.sys.api.enums.user.UserStatusEnum; import cn.stylefeng.roses.kernel.sys.api.enums.user.UserStatusEnum;
import cn.stylefeng.roses.kernel.sys.api.exception.enums.UserExceptionEnum; import cn.stylefeng.roses.kernel.sys.api.exception.enums.UserExceptionEnum;
import cn.stylefeng.roses.kernel.sys.api.expander.SysConfigExpander; import cn.stylefeng.roses.kernel.sys.api.expander.SysConfigExpander;
import cn.stylefeng.roses.kernel.sys.api.pojo.user.OnlineUserItem;
import cn.stylefeng.roses.kernel.sys.api.pojo.user.SimpleUserDTO; import cn.stylefeng.roses.kernel.sys.api.pojo.user.SimpleUserDTO;
import cn.stylefeng.roses.kernel.sys.api.pojo.user.UserOrgDTO; import cn.stylefeng.roses.kernel.sys.api.pojo.user.UserOrgDTO;
import cn.stylefeng.roses.kernel.sys.api.pojo.user.UserValidateDTO; import cn.stylefeng.roses.kernel.sys.api.pojo.user.UserValidateDTO;
@ -41,10 +42,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Date; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -438,6 +436,57 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
return count > 0; return count > 0;
} }
@Override
public OnlineUserItem getUserNameAccountInfo(Long userId) {
if (userId == null) {
return new OnlineUserItem();
}
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysUser::getUserId, userId);
wrapper.select(SysUser::getRealName, SysUser::getAccount);
SysUser sysUser = this.getOne(wrapper, false);
return new OnlineUserItem(userId, sysUser.getRealName(), sysUser.getAccount());
}
@Override
public List<OnlineUserItem> getUserNameAccountInfoListByCondition(List<OnlineUserItem> onlineUserItems, String searchText) {
if (ObjectUtil.isEmpty(onlineUserItems) || ObjectUtil.isEmpty(searchText)) {
return new ArrayList<>();
}
// 在线用户列表的id集合
Set<Long> userIdList = onlineUserItems.stream().map(OnlineUserItem::getUserId).collect(Collectors.toSet());
// 在这些id集合和查询条件中筛选符合条件的用户并组装上他们的姓名和账号
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.in(SysUser::getUserId, userIdList);
wrapper.nested(wrap -> {
wrap.like(SysUser::getRealName, searchText).or().like(SysUser::getAccount, searchText);
});
wrapper.select(SysUser::getUserId, SysUser::getRealName, SysUser::getAccount);
List<SysUser> sysUserList = this.list(wrapper);
List<OnlineUserItem> resultList = new ArrayList<>();
if (ObjectUtil.isEmpty(sysUserList)) {
return resultList;
}
Map<Long, SysUser> userMap = sysUserList.stream().collect(Collectors.toMap(SysUser::getUserId, item -> item));
// 从在线用户中查找包含这些key的元素
for (OnlineUserItem onlineUserItem : onlineUserItems) {
if (userMap.containsKey(onlineUserItem.getUserId())) {
resultList.add(onlineUserItem);
}
}
return resultList;
}
/** /**
* *
* *

View File

@ -0,0 +1,58 @@
package cn.stylefeng.roses.kernel.sys.modular.login.controller;
import cn.stylefeng.roses.kernel.rule.pojo.response.ResponseData;
import cn.stylefeng.roses.kernel.rule.pojo.response.SuccessResponseData;
import cn.stylefeng.roses.kernel.scanner.api.annotation.ApiResource;
import cn.stylefeng.roses.kernel.scanner.api.annotation.GetResource;
import cn.stylefeng.roses.kernel.sys.api.pojo.user.OnlineUserItem;
import cn.stylefeng.roses.kernel.sys.modular.login.pojo.OnlineUserResult;
import cn.stylefeng.roses.kernel.sys.modular.login.service.OnlineUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 线
*
* @author fengshuonan
* @since 2023/7/2 11:25
*/
@RestController
@Slf4j
@ApiResource(name = "获取用户在线信息的接口")
public class OnlineUserController {
@Resource
private OnlineUserService onlineUserService;
/**
* 线
*
* @param searchText
* @author fengshuonan
* @since 2023/7/2 11:26
*/
@GetResource(name = "获取在线用户列表", path = "/getOnlineUserList")
public ResponseData<OnlineUserResult> getOnlineUserList(@RequestParam(value = "searchText", required = false) String searchText) {
OnlineUserResult result = onlineUserService.getOnlineUserList(searchText);
return new SuccessResponseData<>(result);
}
/**
* 线token
*
* @param onlineUserInfo
* @author fengshuonan
* @since 2023/7/2 11:26
*/
@GetResource(name = "获取在线用户列表", path = "/offlineUser")
public ResponseData<?> offlineUser(@RequestBody @Validated(OnlineUserItem.offlineUser.class) OnlineUserItem onlineUserInfo) {
onlineUserService.offlineUser(onlineUserInfo);
return new SuccessResponseData<>();
}
}

View File

@ -0,0 +1,29 @@
package cn.stylefeng.roses.kernel.sys.modular.login.pojo;
import cn.stylefeng.roses.kernel.rule.annotation.ChineseDescription;
import cn.stylefeng.roses.kernel.sys.api.pojo.user.OnlineUserItem;
import lombok.Data;
import java.util.List;
/**
* 线
*
* @author fengshuonan
* @since 2023/7/2 12:29
*/
@Data
public class OnlineUserResult {
/**
* 线
*/
private Integer totalUserCount = 0;
/**
* 线
*/
@ChineseDescription("用户在线列表人数")
private List<OnlineUserItem> onlineUserList;
}

View File

@ -0,0 +1,104 @@
package cn.stylefeng.roses.kernel.sys.modular.login.service;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi;
import cn.stylefeng.roses.kernel.auth.api.context.LoginContext;
import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import cn.stylefeng.roses.kernel.sys.api.SysUserServiceApi;
import cn.stylefeng.roses.kernel.sys.api.exception.enums.UserExceptionEnum;
import cn.stylefeng.roses.kernel.sys.api.pojo.user.OnlineUserItem;
import cn.stylefeng.roses.kernel.sys.modular.login.pojo.OnlineUserResult;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* 线
*
* @author fengshuonan
* @since 2023/7/2 11:25
*/
@Service
public class OnlineUserService {
@Resource
private SessionManagerApi sessionManagerApi;
@Resource
private SysUserServiceApi sysUserServiceApi;
/**
* 线
* <p>
*
*
* @author fengshuonan
* @since 2023/7/2 12:09
*/
public OnlineUserResult getOnlineUserList(String searchText) {
OnlineUserResult onlineUserResult = new OnlineUserResult();
List<LoginUser> loginUsers = sessionManagerApi.onlineUserList();
if (ObjectUtil.isEmpty(loginUsers)) {
return new OnlineUserResult();
}
// 返回总的在线人数
onlineUserResult.setTotalUserCount(loginUsers.size());
// 转化为用户的在线信息
List<OnlineUserItem> onlineUserInfos = new ArrayList<>();
for (LoginUser loginUser : loginUsers) {
OnlineUserItem onlineUserInfo = new OnlineUserItem();
onlineUserInfo.setUserId(loginUser.getUserId());
onlineUserInfo.setToken(loginUser.getToken());
onlineUserInfos.add(onlineUserInfo);
}
// 如果没传查询条件只返回前10条
if (StrUtil.isBlank(searchText)) {
if (onlineUserInfos.size() > 10) {
onlineUserInfos = onlineUserInfos.subList(0, 9);
}
// 用户信息补充姓名和账号返回
for (OnlineUserItem onlineUserInfo : onlineUserInfos) {
OnlineUserItem userNameAccountInfo = sysUserServiceApi.getUserNameAccountInfo(onlineUserInfo.getUserId());
onlineUserInfo.setAccount(userNameAccountInfo.getAccount());
onlineUserInfo.setRealName(userNameAccountInfo.getRealName());
}
onlineUserResult.setOnlineUserList(onlineUserInfos);
return onlineUserResult;
}
// 如果传递了查询条件则从在线用户id和指定查询条件中筛选出来结果
else {
List<OnlineUserItem> resultUserList = sysUserServiceApi.getUserNameAccountInfoListByCondition(onlineUserInfos, searchText);
onlineUserResult.setOnlineUserList(resultUserList);
return onlineUserResult;
}
}
/**
* 线token
*
* @author fengshuonan
* @since 2023/7/2 12:23
*/
public void offlineUser(OnlineUserItem onlineUserInfo) throws ServiceException {
if (!LoginContext.me().getSuperAdminFlag()) {
throw new ServiceException(UserExceptionEnum.KICK_OFF_ERROR);
}
sessionManagerApi.removeSession(onlineUserInfo.getToken());
}
}