Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
查尔斯-BUG万象集
Continew Admin
提交
3116fd3e
Continew Admin
项目概览
查尔斯-BUG万象集
/
Continew Admin
11 个月 前同步成功
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
分析
仓库
DevOps
项目成员
Pages
Continew Admin
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3116fd3e
编写于
1月 21, 2023
作者:
查尔斯-BUG万象集
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
新增:新增系统监控/在线用户功能,并优化部分注释规范
上级
185b7932
变更
24
隐藏空白更改
内联
并排
Showing
24 changed file
with
640 addition
and
48 deletion
+640
-48
README.md
README.md
+5
-4
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalExceptionHandler.java
...rles7c/cnadmin/common/handler/GlobalExceptionHandler.java
+14
-1
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/dto/LoginUser.java
...ava/top/charles7c/cnadmin/common/model/dto/LoginUser.java
+25
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/query/PageQuery.java
...a/top/charles7c/cnadmin/common/model/query/PageQuery.java
+4
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/PageInfo.java
.../java/top/charles7c/cnadmin/common/model/vo/PageInfo.java
+35
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/helper/LoginHelper.java
...top/charles7c/cnadmin/common/util/helper/LoginHelper.java
+24
-1
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/entity/SysLog.java
...va/top/charles7c/cnadmin/monitor/model/entity/SysLog.java
+1
-1
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/query/OnlineUserQuery.java
...harles7c/cnadmin/monitor/model/query/OnlineUserQuery.java
+52
-0
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/vo/LoginLogVO.java
...va/top/charles7c/cnadmin/monitor/model/vo/LoginLogVO.java
+4
-4
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/vo/OnlineUserVO.java
.../top/charles7c/cnadmin/monitor/model/vo/OnlineUserVO.java
+79
-0
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/vo/OperationLogVO.java
...op/charles7c/cnadmin/monitor/model/vo/OperationLogVO.java
+2
-2
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/vo/SystemLogDetailVO.java
...charles7c/cnadmin/monitor/model/vo/SystemLogDetailVO.java
+2
-2
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/vo/SystemLogVO.java
...a/top/charles7c/cnadmin/monitor/model/vo/SystemLogVO.java
+2
-2
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/service/LogService.java
...ava/top/charles7c/cnadmin/monitor/service/LogService.java
+1
-1
continew-admin-ui/src/api/monitor/online.ts
continew-admin-ui/src/api/monitor/online.ts
+35
-0
continew-admin-ui/src/locale/en-US.ts
continew-admin-ui/src/locale/en-US.ts
+2
-0
continew-admin-ui/src/locale/zh-CN.ts
continew-admin-ui/src/locale/zh-CN.ts
+2
-0
continew-admin-ui/src/router/routes/modules/monitor.ts
continew-admin-ui/src/router/routes/modules/monitor.ts
+10
-0
continew-admin-ui/src/views/monitor/log/login/index.vue
continew-admin-ui/src/views/monitor/log/login/index.vue
+3
-13
continew-admin-ui/src/views/monitor/log/operation/index.vue
continew-admin-ui/src/views/monitor/log/operation/index.vue
+4
-17
continew-admin-ui/src/views/monitor/online/index.vue
continew-admin-ui/src/views/monitor/online/index.vue
+202
-0
continew-admin-ui/src/views/monitor/online/locale/en-US.ts
continew-admin-ui/src/views/monitor/online/locale/en-US.ts
+3
-0
continew-admin-ui/src/views/monitor/online/locale/zh-CN.ts
continew-admin-ui/src/views/monitor/online/locale/zh-CN.ts
+3
-0
continew-admin-webapi/src/main/java/top/charles7c/cnadmin/webapi/controller/monitor/OnlineUserController.java
...admin/webapi/controller/monitor/OnlineUserController.java
+126
-0
未找到文件。
README.md
浏览文件 @
3116fd3e
...
...
@@ -251,10 +251,11 @@ continew-admin
│ ├─ views
# 页面模板
│ │ ├─ login
# 登录模块
│ │ ├─ monitor
# 系统监控模块
│ │ │ └─ log
# 日志管理
│ │ │ ├─ login
# 登录日志
│ │ │ ├─ operation
# 操作日志
│ │ │ └─ system
# 系统日志
│ │ │ ├─ log
# 日志管理
│ │ │ │ ├─ login
# 登录日志
│ │ │ │ ├─ operation
# 操作日志
│ │ │ │ └─ system
# 系统日志
│ │ │ └─ online
# 在线用户
│ │ └─ system
# 系统管理模块
│ │ └─ user
# 用户模块
│ │ └─ center
# 个人中心
...
...
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalExceptionHandler.java
浏览文件 @
3116fd3e
...
...
@@ -169,7 +169,20 @@ public class GlobalExceptionHandler {
@ExceptionHandler
(
NotLoginException
.
class
)
public
R
handleNotLoginException
(
NotLoginException
e
,
HttpServletRequest
request
)
{
log
.
error
(
"请求地址'{}',认证失败,无法访问系统资源"
,
request
.
getRequestURI
(),
e
);
String
errorMsg
=
"登录状态已过期,请重新登录"
;
String
errorMsg
;
switch
(
e
.
getType
())
{
case
NotLoginException
.
KICK_OUT
:
errorMsg
=
"您已被踢下线"
;
break
;
case
NotLoginException
.
BE_REPLACED_MESSAGE
:
errorMsg
=
"您已被顶下线"
;
break
;
default
:
errorMsg
=
"登录状态已过期,请重新登录"
;
break
;
}
LogContextHolder
.
setErrorMsg
(
errorMsg
);
return
R
.
fail
(
HttpStatus
.
UNAUTHORIZED
.
value
(),
errorMsg
);
}
...
...
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/dto/LoginUser.java
浏览文件 @
3116fd3e
...
...
@@ -83,4 +83,29 @@ public class LoginUser implements Serializable {
* 创建时间
*/
private
LocalDateTime
createTime
;
/**
* 令牌
*/
private
String
token
;
/**
* 登录 IP
*/
private
String
clientIp
;
/**
* 登录地点
*/
private
String
location
;
/**
* 浏览器
*/
private
String
browser
;
/**
* 登录时间
*/
private
LocalDateTime
loginTime
;
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/query/PageQuery.java
浏览文件 @
3116fd3e
...
...
@@ -78,6 +78,10 @@ public class PageQuery implements Serializable {
this
.
size
=
DEFAULT_SIZE
;
}
public
int
getPage
()
{
return
page
<
0
?
DEFAULT_PAGE
:
page
;
}
/**
* 解析排序条件为 Spring 分页排序实体
*
...
...
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/PageInfo.java
浏览文件 @
3116fd3e
...
...
@@ -16,6 +16,7 @@
package
top.charles7c.cnadmin.common.model.vo
;
import
java.util.ArrayList
;
import
java.util.List
;
import
lombok.Data
;
...
...
@@ -26,6 +27,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
cn.hutool.core.bean.BeanUtil
;
import
cn.hutool.core.collection.CollUtil
;
/**
* 分页信息
...
...
@@ -93,4 +95,37 @@ public class PageInfo<V> {
pageInfo
.
setTotal
(
pageInfo
.
getTotal
());
return
pageInfo
;
}
/**
* 基于列表数据构建分页信息
*
* @param page
* 页码
* @param size
* 每页记录数
* @param list
* 列表数据
* @param <V>
* 列表数据类型
* @return 分页信息
*/
public
static
<
V
>
PageInfo
<
V
>
build
(
int
page
,
int
size
,
List
<
V
>
list
)
{
PageInfo
<
V
>
pageInfo
=
new
PageInfo
<>();
if
(
CollUtil
.
isEmpty
(
list
))
{
return
pageInfo
;
}
pageInfo
.
setTotal
(
list
.
size
());
// 对列表数据进行分页
int
fromIndex
=
(
page
-
1
)
*
size
;
int
toIndex
=
page
*
size
+
size
;
if
(
fromIndex
>
list
.
size
())
{
pageInfo
.
setList
(
new
ArrayList
<>());
}
else
if
(
toIndex
>=
list
.
size
())
{
pageInfo
.
setList
(
list
.
subList
(
fromIndex
,
list
.
size
()));
}
else
{
pageInfo
.
setList
(
list
.
subList
(
fromIndex
,
toIndex
));
}
return
pageInfo
;
}
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/helper/LoginHelper.java
浏览文件 @
3116fd3e
...
...
@@ -16,15 +16,24 @@
package
top.charles7c.cnadmin.common.util.helper
;
import
java.time.LocalDateTime
;
import
javax.servlet.http.HttpServletRequest
;
import
lombok.AccessLevel
;
import
lombok.NoArgsConstructor
;
import
cn.dev33.satoken.context.SaHolder
;
import
cn.dev33.satoken.stp.StpUtil
;
import
cn.hutool.extra.servlet.ServletUtil
;
import
top.charles7c.cnadmin.common.consts.CacheConstants
;
import
top.charles7c.cnadmin.common.model.dto.LogContext
;
import
top.charles7c.cnadmin.common.model.dto.LoginUser
;
import
top.charles7c.cnadmin.common.util.ExceptionUtils
;
import
top.charles7c.cnadmin.common.util.IpUtils
;
import
top.charles7c.cnadmin.common.util.ServletUtils
;
import
top.charles7c.cnadmin.common.util.holder.LogContextHolder
;
/**
* 登录助手
...
...
@@ -42,8 +51,22 @@ public class LoginHelper {
* 登录用户信息
*/
public
static
void
login
(
LoginUser
loginUser
)
{
SaHolder
.
getStorage
().
set
(
CacheConstants
.
LOGIN_USER_CACHE_KEY
,
loginUser
);
if
(
loginUser
==
null
)
{
return
;
}
// 记录登录信息
HttpServletRequest
request
=
ServletUtils
.
getRequest
();
loginUser
.
setClientIp
(
ServletUtil
.
getClientIP
(
request
));
loginUser
.
setLocation
(
IpUtils
.
getCityInfo
(
loginUser
.
getClientIp
()));
loginUser
.
setBrowser
(
ServletUtils
.
getBrowser
(
request
));
LogContext
logContext
=
LogContextHolder
.
get
();
loginUser
.
setLoginTime
(
logContext
!=
null
?
logContext
.
getCreateTime
()
:
LocalDateTime
.
now
());
// 登录保存用户信息
StpUtil
.
login
(
loginUser
.
getUserId
());
loginUser
.
setToken
(
StpUtil
.
getTokenValue
());
SaHolder
.
getStorage
().
set
(
CacheConstants
.
LOGIN_USER_CACHE_KEY
,
loginUser
);
StpUtil
.
getTokenSession
().
set
(
CacheConstants
.
LOGIN_USER_CACHE_KEY
,
loginUser
);
}
...
...
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/entity/SysLog.java
浏览文件 @
3116fd3e
...
...
@@ -39,7 +39,7 @@ public class SysLog implements Serializable {
private
static
final
long
serialVersionUID
=
1L
;
/**
* 日志ID
* 日志
ID
*/
@TableId
private
Long
logId
;
...
...
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/query/OnlineUserQuery.java
0 → 100644
浏览文件 @
3116fd3e
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
top.charles7c.cnadmin.monitor.model.query
;
import
java.util.Date
;
import
java.util.List
;
import
lombok.Data
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
org.springdoc.api.annotations.ParameterObject
;
import
org.springframework.format.annotation.DateTimeFormat
;
/**
* 在线用户查询条件
*
* @author Charles7c
* @since 2023/1/20 23:07
*/
@Data
@ParameterObject
@Schema
(
description
=
"在线用户查询条件"
)
public
class
OnlineUserQuery
{
/**
* 用户昵称
*/
@Schema
(
description
=
"用户昵称"
)
private
String
nickname
;
/**
* 登录时间
*/
@Schema
(
description
=
"登录时间"
)
@DateTimeFormat
(
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
private
List
<
Date
>
loginTime
;
}
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/vo/LoginLogVO.java
浏览文件 @
3116fd3e
...
...
@@ -38,9 +38,9 @@ public class LoginLogVO extends LogVO implements Serializable {
private
static
final
long
serialVersionUID
=
1L
;
/**
* 日志ID
* 日志
ID
*/
@Schema
(
description
=
"日志ID"
)
@Schema
(
description
=
"日志
ID"
)
private
Long
logId
;
/**
...
...
@@ -56,9 +56,9 @@ public class LoginLogVO extends LogVO implements Serializable {
private
LogStatusEnum
status
;
/**
* 登录IP
* 登录
IP
*/
@Schema
(
description
=
"登录IP"
)
@Schema
(
description
=
"登录
IP"
)
private
String
clientIp
;
/**
...
...
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/vo/OnlineUserVO.java
0 → 100644
浏览文件 @
3116fd3e
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
top.charles7c.cnadmin.monitor.model.vo
;
import
java.io.Serializable
;
import
java.time.LocalDateTime
;
import
lombok.Data
;
import
io.swagger.v3.oas.annotations.media.Schema
;
/**
* 在线用户信息
*
* @author Charles7c
* @since 2023/1/20 21:54
*/
@Data
@Schema
(
description
=
"在线用户信息"
)
public
class
OnlineUserVO
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 令牌
*/
@Schema
(
description
=
"令牌"
)
private
String
token
;
/**
* 用户名
*/
@Schema
(
description
=
"用户名"
)
private
String
username
;
/**
* 昵称
*/
@Schema
(
description
=
"昵称"
)
private
String
nickname
;
/**
* 登录 IP
*/
@Schema
(
description
=
"登录 IP"
)
private
String
clientIp
;
/**
* 登录地点
*/
@Schema
(
description
=
"登录地点"
)
private
String
location
;
/**
* 浏览器
*/
@Schema
(
description
=
"浏览器"
)
private
String
browser
;
/**
* 登录时间
*/
@Schema
(
description
=
"登录时间"
)
private
LocalDateTime
loginTime
;
}
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/vo/OperationLogVO.java
浏览文件 @
3116fd3e
...
...
@@ -38,9 +38,9 @@ public class OperationLogVO extends LogVO implements Serializable {
private
static
final
long
serialVersionUID
=
1L
;
/**
* 日志ID
* 日志
ID
*/
@Schema
(
description
=
"日志ID"
)
@Schema
(
description
=
"日志
ID"
)
private
Long
logId
;
/**
...
...
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/vo/SystemLogDetailVO.java
浏览文件 @
3116fd3e
...
...
@@ -36,9 +36,9 @@ public class SystemLogDetailVO extends LogVO implements Serializable {
private
static
final
long
serialVersionUID
=
1L
;
/**
* 日志ID
* 日志
ID
*/
@Schema
(
description
=
"日志ID"
)
@Schema
(
description
=
"日志
ID"
)
private
Long
logId
;
/**
...
...
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/vo/SystemLogVO.java
浏览文件 @
3116fd3e
...
...
@@ -36,9 +36,9 @@ public class SystemLogVO extends LogVO implements Serializable {
private
static
final
long
serialVersionUID
=
1L
;
/**
* 日志ID
* 日志
ID
*/
@Schema
(
description
=
"日志ID"
)
@Schema
(
description
=
"日志
ID"
)
private
Long
logId
;
/**
...
...
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/service/LogService.java
浏览文件 @
3116fd3e
...
...
@@ -71,7 +71,7 @@ public interface LogService {
* 查看系统日志详情
*
* @param logId
* 日志ID
* 日志
ID
* @return 系统日志详情
*/
SystemLogDetailVO
detail
(
Long
logId
);
...
...
continew-admin-ui/src/api/monitor/online.ts
0 → 100644
浏览文件 @
3116fd3e
import
axios
from
'
axios
'
;
import
qs
from
'
query-string
'
;
export
interface
OnlineUserRecord
{
token
:
string
;
username
:
string
;
nickname
:
string
;
clientIp
:
string
;
location
:
string
;
browser
:
string
;
loginTime
:
string
;
}
export
interface
OnlineUserParams
extends
Partial
<
OnlineUserRecord
>
{
page
:
number
;
size
:
number
;
sort
:
Array
<
string
>
;
}
export
interface
OnlineUserListRes
{
list
:
OnlineUserRecord
[];
total
:
number
;
}
export
function
queryOnlineUserList
(
params
:
OnlineUserParams
)
{
return
axios
.
get
<
OnlineUserListRes
>
(
'
/monitor/online/user
'
,
{
params
,
paramsSerializer
:
(
obj
)
=>
{
return
qs
.
stringify
(
obj
);
},
});
}
export
function
kickout
(
token
:
string
)
{
return
axios
.
delete
(
`/monitor/online/user/
${
token
}
`
);
}
\ No newline at end of file
continew-admin-ui/src/locale/en-US.ts
浏览文件 @
3116fd3e
...
...
@@ -8,6 +8,7 @@ import localeMonitor from '@/views/dashboard/monitor/locale/en-US';
import
localeDataAnalysis
from
'
@/views/visualization/data-analysis/locale/en-US
'
;
import
localeMultiDAnalysis
from
'
@/views/visualization/multi-dimension-data-analysis/locale/en-US
'
;
import
localeOnlineUser
from
'
@/views/monitor/online/locale/en-US
'
;
import
localeLoginLog
from
'
@/views/monitor/log/login/locale/en-US
'
;
import
localeOperationLog
from
'
@/views/monitor/log/operation/locale/en-US
'
;
import
localeSystemLog
from
'
@/views/monitor/log/system/locale/en-US
'
;
...
...
@@ -57,6 +58,7 @@ export default {
...
localeDataAnalysis
,
...
localeMultiDAnalysis
,
...
localeOnlineUser
,
...
localeLoginLog
,
...
localeOperationLog
,
...
localeSystemLog
,
...
...
continew-admin-ui/src/locale/zh-CN.ts
浏览文件 @
3116fd3e
...
...
@@ -8,6 +8,7 @@ import localeMonitor from '@/views/dashboard/monitor/locale/zh-CN';
import
localeDataAnalysis
from
'
@/views/visualization/data-analysis/locale/zh-CN
'
;
import
localeMultiDAnalysis
from
'
@/views/visualization/multi-dimension-data-analysis/locale/zh-CN
'
;
import
localeOnlineUser
from
'
@/views/monitor/online/locale/zh-CN
'
;
import
localeLoginLog
from
'
@/views/monitor/log/login/locale/zh-CN
'
;
import
localeOperationLog
from
'
@/views/monitor/log/operation/locale/zh-CN
'
;
import
localeSystemLog
from
'
@/views/monitor/log/system/locale/zh-CN
'
;
...
...
@@ -57,6 +58,7 @@ export default {
...
localeDataAnalysis
,
...
localeMultiDAnalysis
,
...
localeOnlineUser
,
...
localeLoginLog
,
...
localeOperationLog
,
...
localeSystemLog
,
...
...
continew-admin-ui/src/router/routes/modules/monitor.ts
浏览文件 @
3116fd3e
...
...
@@ -12,6 +12,16 @@ const Monitor: AppRouteRecordRaw = {
order
:
2
,
},
children
:
[
{
path
:
'
/online
'
,
name
:
'
OnlineUser
'
,
component
:
()
=>
import
(
'
@/views/monitor/online/index.vue
'
),
meta
:
{
locale
:
'
menu.online.user.list
'
,
requiresAuth
:
true
,
roles
:
[
'
*
'
],
},
},
{
path
:
'
log/login
'
,
name
:
'
LoginLog
'
,
...
...
continew-admin-ui/src/views/monitor/log/login/index.vue
浏览文件 @
3116fd3e
...
...
@@ -4,15 +4,8 @@
<a-card
class=
"general-card"
:title=
"$t('menu.log.login.list')"
>
<a-row
style=
"margin-bottom: 15px"
>
<a-col
:span=
"24"
>
<a-form
ref=
"queryFormRef"
:model=
"queryFormData"
layout=
"inline"
>
<a-form-item
field=
"status"
hide-label
>
<a-form
ref=
"queryFormRef"
:model=
"queryFormData"
layout=
"inline"
>
<a-form-item
field=
"status"
hide-label
>
<a-select
v-model=
"queryFormData.status"
:options=
"statusOptions"
...
...
@@ -21,10 +14,7 @@
style=
"width: 150px;"
/>
</a-form-item>
<a-form-item
field=
"createTime"
hide-label
>
<a-form-item
field=
"createTime"
hide-label
>
<date-range-picker
v-model=
"queryFormData.createTime"
/>
</a-form-item>
<a-button
type=
"primary"
@
click=
"toQuery"
>
...
...
continew-admin-ui/src/views/monitor/log/operation/index.vue
浏览文件 @
3116fd3e
...
...
@@ -4,15 +4,8 @@
<a-card
class=
"general-card"
:title=
"$t('menu.log.operation.list')"
>
<a-row
style=
"margin-bottom: 15px"
>
<a-col
:span=
"24"
>
<a-form
ref=
"queryFormRef"
:model=
"queryFormData"
layout=
"inline"
>
<a-form-item
field=
"description"
hide-label
>
<a-form
ref=
"queryFormRef"
:model=
"queryFormData"
layout=
"inline"
>
<a-form-item
field=
"description"
hide-label
>
<a-input
v-model=
"queryFormData.description"
placeholder=
"输入操作内容搜索"
...
...
@@ -21,10 +14,7 @@
@
press-enter=
"toQuery"
/>
</a-form-item>
<a-form-item
field=
"status"
hide-label
>
<a-form-item
field=
"status"
hide-label
>
<a-select
v-model=
"queryFormData.status"
:options=
"statusOptions"
...
...
@@ -33,10 +23,7 @@
style=
"width: 150px;"
/>
</a-form-item>
<a-form-item
field=
"createTime"
hide-label
>
<a-form-item
field=
"createTime"
hide-label
>
<date-range-picker
v-model=
"queryFormData.createTime"
/>
</a-form-item>
<a-button
type=
"primary"
@
click=
"toQuery"
>
...
...
continew-admin-ui/src/views/monitor/online/index.vue
0 → 100644
浏览文件 @
3116fd3e
<
template
>
<div
class=
"container"
>
<Breadcrumb
:items=
"['menu.monitor', 'menu.online.user.list']"
/>
<a-card
class=
"general-card"
:title=
"$t('menu.online.user.list')"
>
<a-row
style=
"margin-bottom: 15px"
>
<a-col
:span=
"24"
>
<a-form
ref=
"queryFormRef"
:model=
"queryFormData"
layout=
"inline"
>
<a-form-item
field=
"nickname"
hide-label
>
<a-input
v-model=
"queryFormData.nickname"
placeholder=
"输入用户昵称搜索"
allow-clear
style=
"width: 150px;"
@
press-enter=
"toQuery"
/>
</a-form-item>
<a-form-item
field=
"loginTime"
hide-label
>
<date-range-picker
v-model=
"queryFormData.loginTime"
/>
</a-form-item>
<a-button
type=
"primary"
@
click=
"toQuery"
>
<template
#icon
>
<icon-search
/>
</
template
>
查询
</a-button>
<a-button
@
click=
"resetQuery"
>
<
template
#icon
>
<icon-refresh
/>
</
template
>
重置
</a-button>
</a-form>
</a-col>
</a-row>
<a-table
:columns=
"columns"
:data=
"renderData"
:pagination=
"paginationProps"
row-key=
"logId"
:bordered=
"false"
:stripe=
"true"
:loading=
"loading"
size=
"large"
@
page-change=
"handlePageChange"
@
page-size-change=
"handlePageSizeChange"
>
<
template
#index=
"{ rowIndex }"
>
{{
rowIndex
+
1
+
(
pagination
.
current
-
1
)
*
pagination
.
pageSize
}}
</
template
>
<
template
#nickname=
"{ record }"
>
{{
record
.
nickname
}}
(
{{
record
.
username
}}
)
</
template
>
<
template
#operations=
"{ record }"
>
<a-button
v-permission=
"['admin']"
type=
"text"
size=
"small"
:title=
"currentToken === record.token ? '不能强退当前登录' : ''"
:disabled=
"currentToken === record.token"
@
click=
"handleClick(record.token)"
>
强退
</a-button>
</
template
>
</a-table>
</a-card>
</div>
</template>
<
script
lang=
"ts"
setup
>
import
{
computed
,
ref
,
reactive
}
from
'
vue
'
;
import
useLoading
from
'
@/hooks/loading
'
;
import
{
Message
}
from
'
@arco-design/web-vue
'
;
import
{
queryOnlineUserList
,
OnlineUserRecord
,
OnlineUserParams
,
kickout
}
from
'
@/api/monitor/online
'
;
import
{
Pagination
}
from
'
@/types/global
'
;
import
{
PaginationProps
}
from
'
@arco-design/web-vue
'
;
import
type
{
TableColumnData
}
from
'
@arco-design/web-vue/es/table/interface
'
;
import
{
FormInstance
}
from
'
@arco-design/web-vue/es/form
'
;
import
{
getToken
}
from
'
@/utils/auth
'
;
const
{
loading
,
setLoading
}
=
useLoading
(
true
);
const
currentToken
=
computed
(()
=>
getToken
());
const
queryFormRef
=
ref
<
FormInstance
>
();
const
queryFormData
=
ref
({
nickname
:
''
,
status
:
undefined
,
loginTime
:
[],
});
// 查询
const
toQuery
=
()
=>
{
fetchData
({
page
:
pagination
.
current
,
size
:
pagination
.
pageSize
,
sort
:
[
'
createTime,desc
'
],
...
queryFormData
.
value
,
}
as
unknown
as
OnlineUserParams
);
};
// 重置
const
resetQuery
=
async
()
=>
{
await
queryFormRef
.
value
?.
resetFields
();
await
fetchData
();
};
const
renderData
=
ref
<
OnlineUserRecord
[]
>
([]);
const
basePagination
:
Pagination
=
{
current
:
1
,
pageSize
:
10
,
};
const
pagination
=
reactive
({
...
basePagination
,
});
const
paginationProps
=
computed
(():
PaginationProps
=>
{
return
{
showTotal
:
true
,
showPageSize
:
true
,
total
:
pagination
.
total
,
current
:
pagination
.
current
,
}
});
const
columns
=
computed
<
TableColumnData
[]
>
(()
=>
[
{
title
:
'
序号
'
,
dataIndex
:
'
index
'
,
slotName
:
'
index
'
,
},
{
title
:
'
用户昵称
'
,
dataIndex
:
'
nickname
'
,
slotName
:
'
nickname
'
,
},
{
title
:
'
登录 IP
'
,
dataIndex
:
'
clientIp
'
,
},
{
title
:
'
登录地点
'
,
dataIndex
:
'
location
'
,
},
{
title
:
'
浏览器
'
,
dataIndex
:
'
browser
'
,
},
{
title
:
'
登录时间
'
,
dataIndex
:
'
loginTime
'
,
},
{
title
:
'
操作
'
,
slotName
:
'
operations
'
,
align
:
'
center
'
,
},
]);
// 分页查询列表
const
fetchData
=
async
(
params
:
OnlineUserParams
=
{
page
:
1
,
size
:
10
,
sort
:
[
'
createTime,desc
'
]
}
)
=>
{
setLoading
(
true
);
try
{
const
{
data
}
=
await
queryOnlineUserList
(
params
);
renderData
.
value
=
data
.
list
;
pagination
.
current
=
params
.
page
;
pagination
.
total
=
data
.
total
;
}
finally
{
setLoading
(
false
);
}
};
const
handlePageChange
=
(
current
:
number
)
=>
{
fetchData
({
page
:
current
,
size
:
pagination
.
pageSize
,
sort
:
[
'
createTime,desc
'
]
});
};
const
handlePageSizeChange
=
(
pageSize
:
number
)
=>
{
fetchData
({
page
:
pagination
.
current
,
size
:
pageSize
,
sort
:
[
'
createTime,desc
'
]
});
};
fetchData
();
// 强退
const
handleClick
=
async
(
token
:
string
)
=>
{
const
res
=
await
kickout
(
token
);
if
(
res
.
success
)
Message
.
success
(
res
.
msg
);
};
</
script
>
<
script
lang=
"ts"
>
export
default
{
name
:
'
OnlineUser
'
,
};
</
script
>
<
style
scoped
lang=
"less"
>
.container {
padding: 0 20px 20px 20px;
}
:deep(.arco-table-th) {
&:last-child {
.arco-table-th-item-title {
margin-left: 16px;
}
}
}
</
style
>
continew-admin-ui/src/views/monitor/online/locale/en-US.ts
0 → 100644
浏览文件 @
3116fd3e
export
default
{
'
menu.online.user.list
'
:
'
Online user
'
,
};
continew-admin-ui/src/views/monitor/online/locale/zh-CN.ts
0 → 100644
浏览文件 @
3116fd3e
export
default
{
'
menu.online.user.list
'
:
'
在线用户
'
,
};
continew-admin-webapi/src/main/java/top/charles7c/cnadmin/webapi/controller/monitor/OnlineUserController.java
0 → 100644
浏览文件 @
3116fd3e
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
top.charles7c.cnadmin.webapi.controller.monitor
;
import
java.util.ArrayList
;
import
java.util.Comparator
;
import
java.util.Date
;
import
java.util.List
;
import
lombok.RequiredArgsConstructor
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
org.springframework.http.MediaType
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
cn.dev33.satoken.dao.SaTokenDao
;
import
cn.dev33.satoken.session.SaSession
;
import
cn.dev33.satoken.stp.StpUtil
;
import
cn.hutool.core.bean.BeanUtil
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.date.DateUtil
;
import
cn.hutool.core.util.StrUtil
;
import
top.charles7c.cnadmin.common.consts.CacheConstants
;
import
top.charles7c.cnadmin.common.model.dto.LoginUser
;
import
top.charles7c.cnadmin.common.model.query.PageQuery
;
import
top.charles7c.cnadmin.common.model.vo.PageInfo
;
import
top.charles7c.cnadmin.common.model.vo.R
;
import
top.charles7c.cnadmin.common.util.validate.ValidationUtils
;
import
top.charles7c.cnadmin.monitor.model.query.OnlineUserQuery
;
import
top.charles7c.cnadmin.monitor.model.vo.*
;
/**
* 在线用户 API
*
* @author Charles7c
* @since 2023/1/20 21:51
*/
@Tag
(
name
=
"在线用户 API"
)
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping
(
value
=
"/monitor/online/user"
,
produces
=
MediaType
.
APPLICATION_JSON_VALUE
)
public
class
OnlineUserController
{
@Operation
(
summary
=
"分页查询在线用户列表"
)
@GetMapping
public
R
<
PageInfo
<
OnlineUserVO
>>
list
(
@Validated
OnlineUserQuery
query
,
@Validated
PageQuery
pageQuery
)
{
List
<
LoginUser
>
loginUserList
=
new
ArrayList
<>();
List
<
String
>
tokenKeyList
=
StpUtil
.
searchTokenValue
(
""
,
0
,
-
1
,
false
);
for
(
String
tokenKey
:
tokenKeyList
)
{
String
token
=
StrUtil
.
subAfter
(
tokenKey
,
":"
,
true
);
// 忽略已过期或失效 token
if
(
StpUtil
.
stpLogic
.
getTokenActivityTimeoutByToken
(
token
)
<
SaTokenDao
.
NEVER_EXPIRE
)
{
continue
;
}
// 获取 Token Session
SaSession
saSession
=
StpUtil
.
getTokenSessionByToken
(
token
);
LoginUser
loginUser
=
saSession
.
get
(
CacheConstants
.
LOGIN_USER_CACHE_KEY
,
new
LoginUser
());
// 检查是否符合查询条件
if
(
Boolean
.
TRUE
.
equals
(
checkQuery
(
query
,
loginUser
)))
{
loginUserList
.
add
(
loginUser
);
}
}
// 构建分页数据
List
<
OnlineUserVO
>
onlineUserList
=
BeanUtil
.
copyToList
(
loginUserList
,
OnlineUserVO
.
class
);
CollUtil
.
sort
(
onlineUserList
,
Comparator
.
comparing
(
OnlineUserVO:
:
getLoginTime
).
reversed
());
PageInfo
<
OnlineUserVO
>
pageInfo
=
PageInfo
.
build
(
pageQuery
.
getPage
(),
pageQuery
.
getSize
(),
onlineUserList
);
return
R
.
ok
(
pageInfo
);
}
/**
* 检查是否符合查询条件
*
* @param query
* 查询条件
* @param loginUser
* 登录用户信息
* @return 是否符合查询条件
*/
private
boolean
checkQuery
(
OnlineUserQuery
query
,
LoginUser
loginUser
)
{
boolean
flag1
=
true
;
String
nickname
=
query
.
getNickname
();
if
(
StrUtil
.
isNotBlank
(
nickname
))
{
flag1
=
loginUser
.
getUsername
().
contains
(
nickname
)
||
loginUser
.
getNickname
().
contains
(
nickname
);
}
boolean
flag2
=
true
;
List
<
Date
>
loginTime
=
query
.
getLoginTime
();
if
(
CollUtil
.
isNotEmpty
(
loginTime
))
{
flag2
=
DateUtil
.
isIn
(
DateUtil
.
date
(
loginUser
.
getLoginTime
()).
toJdkDate
(),
loginTime
.
get
(
0
),
loginTime
.
get
(
1
));
}
return
flag1
&&
flag2
;
}
@Operation
(
summary
=
"强退在线用户"
)
@DeleteMapping
(
"/{token}"
)
public
R
kickout
(
@PathVariable
String
token
)
{
String
currentToken
=
StpUtil
.
getTokenValue
();
ValidationUtils
.
throwIfEqual
(
token
,
currentToken
,
"不能强退当前登录"
);
StpUtil
.
kickoutByTokenValue
(
token
);
return
R
.
ok
(
"强退成功"
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录