mirror of https://gitee.com/stylefeng/roses
【7.6.0】【sys】【loginuser】更新查询在线用户列表接口
parent
e883c39ebf
commit
40b8ef8fad
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
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.UserValidateDTO;
|
||||
|
||||
|
@ -94,4 +95,26 @@ public interface SysUserServiceApi {
|
|||
*/
|
||||
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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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", "无法操作,只有超级管理员可以踢下线用户");
|
||||
|
||||
/**
|
||||
* 错误编码
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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.exception.enums.UserExceptionEnum;
|
||||
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.UserOrgDTO;
|
||||
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 javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
@ -438,6 +436,57 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取信息
|
||||
*
|
||||
|
|
|
@ -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<>();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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());
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue