Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
查尔斯-BUG万象集
Continew Admin
提交
f4ea2d44
Continew Admin
项目概览
查尔斯-BUG万象集
/
Continew Admin
8 个月 前同步成功
通知
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,体验更适合开发者的 AI 搜索 >>
提交
f4ea2d44
编写于
1月 16, 2023
作者:
查尔斯-BUG万象集
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
新增:个人中心新增查询操作日志功能,优化日志表结构,并支持关闭记录内网 IP 操作
上级
79c741b6
变更
36
隐藏空白更改
内联
并排
Showing
36 changed file
with
1270 addition
and
117 deletion
+1270
-117
README.md
README.md
+10
-4
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/annotation/Query.java
...n/java/top/charles7c/cnadmin/common/annotation/Query.java
+113
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalExceptionHandler.java
...rles7c/cnadmin/common/handler/GlobalExceptionHandler.java
+5
-5
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/dto/LogContext.java
...va/top/charles7c/cnadmin/common/model/dto/LogContext.java
+2
-3
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/query/PageQuery.java
...a/top/charles7c/cnadmin/common/model/query/PageQuery.java
+127
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/PageInfo.java
.../java/top/charles7c/cnadmin/common/model/vo/PageInfo.java
+96
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/R.java
...rc/main/java/top/charles7c/cnadmin/common/model/vo/R.java
+10
-13
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/ReflectUtils.java
.../java/top/charles7c/cnadmin/common/util/ReflectUtils.java
+66
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/helper/QueryHelper.java
...top/charles7c/cnadmin/common/util/helper/QueryHelper.java
+216
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/holder/LogContextHolder.java
...harles7c/cnadmin/common/util/holder/LogContextHolder.java
+12
-12
continew-admin-monitor/pom.xml
continew-admin-monitor/pom.xml
+2
-2
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/annotation/Log.java
...in/java/top/charles7c/cnadmin/monitor/annotation/Log.java
+2
-2
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/config/properties/LogProperties.java
...es7c/cnadmin/monitor/config/properties/LogProperties.java
+12
-7
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/enums/LogResultEnum.java
...va/top/charles7c/cnadmin/monitor/enums/LogResultEnum.java
+9
-7
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/interceptor/LogInterceptor.java
...charles7c/cnadmin/monitor/interceptor/LogInterceptor.java
+39
-29
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/mapper/LogMapper.java
.../java/top/charles7c/cnadmin/monitor/mapper/LogMapper.java
+1
-1
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/entity/SysLog.java
...va/top/charles7c/cnadmin/monitor/model/entity/SysLog.java
+10
-10
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/query/OperationLogQuery.java
...rles7c/cnadmin/monitor/model/query/OperationLogQuery.java
+50
-0
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/vo/OperationLogVO.java
...op/charles7c/cnadmin/monitor/model/vo/OperationLogVO.java
+95
-0
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-monitor/src/main/java/top/charles7c/cnadmin/monitor/service/OperationLogService.java
...harles7c/cnadmin/monitor/service/OperationLogService.java
+42
-0
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/service/impl/LogServiceImpl.java
...harles7c/cnadmin/monitor/service/impl/LogServiceImpl.java
+1
-1
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/service/impl/OperationLogServiceImpl.java
...cnadmin/monitor/service/impl/OperationLogServiceImpl.java
+90
-0
continew-admin-ui/src/api/monitor/operation-log.ts
continew-admin-ui/src/api/monitor/operation-log.ts
+34
-0
continew-admin-ui/src/assets/style/global.less
continew-admin-ui/src/assets/style/global.less
+3
-0
continew-admin-ui/src/store/modules/login/index.ts
continew-admin-ui/src/store/modules/login/index.ts
+1
-1
continew-admin-ui/src/store/modules/login/types.ts
continew-admin-ui/src/store/modules/login/types.ts
+1
-1
continew-admin-ui/src/views/login/components/login-form.vue
continew-admin-ui/src/views/login/components/login-form.vue
+1
-1
continew-admin-ui/src/views/system/user/center/components/operation-log.vue
...src/views/system/user/center/components/operation-log.vue
+142
-0
continew-admin-ui/src/views/system/user/center/index.vue
continew-admin-ui/src/views/system/user/center/index.vue
+4
-0
continew-admin-ui/src/views/system/user/center/locale/en-US.ts
...new-admin-ui/src/views/system/user/center/locale/en-US.ts
+1
-0
continew-admin-ui/src/views/system/user/center/locale/zh-CN.ts
...new-admin-ui/src/views/system/user/center/locale/zh-CN.ts
+1
-0
continew-admin-webapi/pom.xml
continew-admin-webapi/pom.xml
+0
-6
continew-admin-webapi/src/main/java/top/charles7c/cnadmin/webapi/controller/monitor/OperationLogController.java
...min/webapi/controller/monitor/OperationLogController.java
+58
-0
continew-admin-webapi/src/main/resources/application.yml
continew-admin-webapi/src/main/resources/application.yml
+7
-5
continew-admin-webapi/src/main/resources/db/changelog/v0.0.1/continew-admin_table.sql
...in/resources/db/changelog/v0.0.1/continew-admin_table.sql
+6
-6
未找到文件。
README.md
浏览文件 @
f4ea2d44
...
...
@@ -134,9 +134,10 @@ continew-admin # 全局通用项目配置及依赖版本管理
│ │ └─ cnadmin
│ │ ├─ webapi
│ │ │ └─ controller
│ │ │ ├─ auth
# 认证相关 API
│ │ │ ├─ common
# 公共相关 API(例如:验证码 API 等)
│ │ │ └─ system
# 系统管理相关 API
│ │ │ ├─ auth
# 认证相关 API
│ │ │ ├─ common
# 公共相关 API(例如:验证码 API 等)
│ │ │ ├─ monitor
# 系统监控相关 API
│ │ │ └─ system
# 系统管理相关 API
│ │ └─ ContinewAdminApplication.java
# 启动入口
│ └─ resources
# 工程配置目录
│ ├─ db.changelog
# 数据库脚本文件
...
...
@@ -159,7 +160,9 @@ continew-admin # 全局通用项目配置及依赖版本管理
│ │ ├─ interceptor
# 系统监控相关拦截器
│ │ ├─ mapper
# 系统监控相关 Mapper
│ │ ├─ model
# 系统监控相关模型
│ │ │ └─ entity
# 系统监控相关实体对象
│ │ │ ├─ entity
# 系统监控相关实体对象
│ │ │ ├─ query
# 系统监控相关查询条件
│ │ │ └─ vo
# 系统监控相关 VO(View Object)
│ │ └─ service
# 系统监控相关业务接口及实现类
│ │ └─ impl
# 系统监控相关业务实现类
│ └─ resources
# 工程配置目录
...
...
@@ -197,6 +200,7 @@ continew-admin # 全局通用项目配置及依赖版本管理
│ └─ charles7c
│ └─ cnadmin
│ └─ common
│ ├─ annotation
# 公共注解
│ ├─ config
# 公共配置
│ │ ├─ jackson
# Jackson 配置
│ │ ├─ mybatis
# MyBatis Plus 配置
...
...
@@ -209,6 +213,7 @@ continew-admin # 全局通用项目配置及依赖版本管理
│ ├─ model
# 公共模型
│ │ ├─ dto
# 公共 DTO(Data Transfer Object)
│ │ ├─ entity
# 公共实体对象
│ │ ├─ query
# 公共查询条件
│ │ └─ vo
# 公共 VO(View Object)
│ └─ util
# 公共工具类
│ ├─ helper
# 公共 Helper(助手)
...
...
@@ -226,6 +231,7 @@ continew-admin
│ ├─ api
# 请求接口
│ │ ├─ auth
# 认证模块
│ │ ├─ common
# 公共模块
│ │ ├─ monitor
# 系统监控模块
│ │ └─ system
# 系统管理模块
│ ├─ assets
# 静态资源
│ │ ├─ images
# 图片资源
...
...
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/annotation/Query.java
0 → 100644
浏览文件 @
f4ea2d44
/*
* 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.common.annotation
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* 查询注解
*
* @author Charles7c
* @since 2023/1/15 18:01
*/
@Target
(
ElementType
.
FIELD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
Query
{
/**
* 属性名(默认和使用该注解的属性的名称一致)
*/
String
property
()
default
""
;
/**
* 查询类型(等值查询、模糊查询、范围查询等)
*/
Type
type
()
default
Type
.
EQUAL
;
/**
* 多属性模糊查询,仅支持 String 类型属性,多个属性之间用逗号分隔
* <p>
* 例如:@Query(blurry = "username,email") 表示根据用户名和邮箱模糊查询
* </p>
*/
String
blurry
()
default
""
;
/**
* 查询类型
*/
enum
Type
{
/**
* 等值查询,例如:WHERE `age` = 18
*/
EQUAL
,
/**
* 非等值查询,例如:WHERE `age` != 18
*/
NOT_EQUAL
,
/**
* 大于查询,例如:WHERE `age` > 18
*/
GREATER_THAN
,
/**
* 小于查询,例如:WHERE `age` < 18
*/
LESS_THAN
,
/**
* 大于等于查询,例如:WHERE `age` >= 18
*/
GREATER_THAN_OR_EQUAL
,
/**
* 小于等于查询,例如:WHERE `age` <= 18
*/
LESS_THAN_OR_EQUAL
,
/**
* 范围查询,例如:WHERE `age` BETWEEN 10 AND 18
*/
BETWEEN
,
/**
* 左模糊查询,例如:WHERE `nickname` LIKE '%张'
*/
LEFT_LIKE
,
/**
* 中模糊查询,例如:WHERE `nickname` LIKE '%雪%'
*/
INNER_LIKE
,
/**
* 右模糊查询,例如:WHERE `nickname` LIKE '雪%'
*/
RIGHT_LIKE
,
/**
* 包含查询,例如:WHERE `age` IN (10, 20, 30)
*/
IN
,
/**
* 不包含查询,例如:WHERE `age` NOT IN (20, 30)
*/
NOT_IN
,
/**
* 空查询,例如:WHERE `email` IS NULL
*/
IS_NULL
,
/**
* 非空查询,例如:WHERE `email` IS NOT NULL
*/
NOT_NULL
,;
}
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalExceptionHandler.java
浏览文件 @
f4ea2d44
...
...
@@ -41,7 +41,7 @@ import cn.hutool.core.util.StrUtil;
import
top.charles7c.cnadmin.common.exception.BadRequestException
;
import
top.charles7c.cnadmin.common.exception.ServiceException
;
import
top.charles7c.cnadmin.common.model.dto.
OperationLog
;
import
top.charles7c.cnadmin.common.model.dto.
LogContext
;
import
top.charles7c.cnadmin.common.model.vo.R
;
import
top.charles7c.cnadmin.common.util.ExceptionUtils
;
import
top.charles7c.cnadmin.common.util.StreamUtils
;
...
...
@@ -179,15 +179,15 @@ public class GlobalExceptionHandler {
}
/**
*
操作日志
保存异常信息
*
在系统日志上下文中
保存异常信息
*
* @param e
* 异常信息
*/
private
void
setException
(
Exception
e
)
{
OperationLog
operationLog
=
LogContextHolder
.
get
();
if
(
operationLog
!=
null
)
{
operationLog
.
setException
(
e
);
LogContext
logContext
=
LogContextHolder
.
get
();
if
(
logContext
!=
null
)
{
logContext
.
setException
(
e
);
}
}
}
\ No newline at end of file
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/dto/
OperationLog
.java
→
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/dto/
LogContext
.java
浏览文件 @
f4ea2d44
...
...
@@ -21,13 +21,13 @@ import java.time.LocalDateTime;
import
lombok.Data
;
/**
*
操作日志
*
系统日志上下文
*
* @author Charles7c
* @since 2022/12/25 8:59
*/
@Data
public
class
OperationLog
{
public
class
LogContext
{
/**
* 操作人
...
...
@@ -43,5 +43,4 @@ public class OperationLog {
* 异常
*/
private
Exception
exception
;
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/query/PageQuery.java
0 → 100644
浏览文件 @
f4ea2d44
/*
* 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.common.model.query
;
import
java.io.Serializable
;
import
java.util.ArrayList
;
import
java.util.List
;
import
lombok.Data
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
org.springdoc.api.annotations.ParameterObject
;
import
org.springframework.data.domain.Sort
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.core.metadata.OrderItem
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.util.ArrayUtil
;
import
cn.hutool.core.util.StrUtil
;
/**
* 分页查询条件
*
* @author Charles7c
* @since 2023/1/15 10:59
*/
@Data
@ParameterObject
@Schema
(
description
=
"分页查询条件"
)
public
class
PageQuery
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 页码
*/
@Schema
(
description
=
"页码"
)
private
int
page
;
/**
* 每页记录数
*/
@Schema
(
description
=
"每页记录数"
)
private
int
size
;
/**
* 排序条件
*/
@Schema
(
description
=
"排序条件"
,
example
=
"sort=published,desc&sort=title,asc"
)
private
String
[]
sort
;
/** 默认页码:1 */
private
static
final
int
DEFAULT_PAGE
=
1
;
/** 默认每页记录数:int 最大值 */
private
static
final
int
DEFAULT_SIZE
=
Integer
.
MAX_VALUE
;
private
static
final
String
DELIMITER
=
","
;
public
PageQuery
()
{
this
.
page
=
DEFAULT_PAGE
;
this
.
size
=
DEFAULT_SIZE
;
}
/**
* 解析排序条件为 Spring 分页排序实体
*
* @return Spring 分页排序实体
*/
public
Sort
getSort
()
{
if
(
ArrayUtil
.
isEmpty
(
sort
))
{
return
Sort
.
unsorted
();
}
List
<
Sort
.
Order
>
orders
=
new
ArrayList
<>(
sort
.
length
);
if
(
sort
[
0
].
contains
(
DELIMITER
))
{
// e.g "sort=published,desc&sort=title,asc"
for
(
String
s
:
sort
)
{
String
[]
sortArr
=
s
.
split
(
DELIMITER
);
Sort
.
Order
order
=
new
Sort
.
Order
(
Sort
.
Direction
.
valueOf
(
sortArr
[
1
].
toUpperCase
()),
sortArr
[
0
]);
orders
.
add
(
order
);
}
}
else
{
// e.g "sort=published,desc"
Sort
.
Order
order
=
new
Sort
.
Order
(
Sort
.
Direction
.
valueOf
(
sort
[
1
].
toUpperCase
()),
sort
[
0
]);
orders
.
add
(
order
);
}
return
Sort
.
by
(
orders
);
}
/**
* 基于分页查询条件转换为 MyBatis Plus 分页条件
*
* @param <T>
* 列表数据类型
* @return MyBatis Plus 分页条件
*/
public
<
T
>
IPage
<
T
>
toPage
()
{
Page
<
T
>
mybatisPage
=
new
Page
<>(
this
.
getPage
(),
this
.
getSize
());
Sort
pageSort
=
this
.
getSort
();
if
(
CollUtil
.
isNotEmpty
(
pageSort
))
{
for
(
Sort
.
Order
order
:
pageSort
)
{
OrderItem
orderItem
=
new
OrderItem
();
orderItem
.
setAsc
(
order
.
isAscending
());
orderItem
.
setColumn
(
StrUtil
.
toUnderlineCase
(
order
.
getProperty
()));
mybatisPage
.
addOrder
(
orderItem
);
}
}
return
mybatisPage
;
}
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/PageInfo.java
0 → 100644
浏览文件 @
f4ea2d44
/*
* 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.common.model.vo
;
import
java.util.List
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
cn.hutool.core.bean.BeanUtil
;
/**
* 分页信息
*
* @param <V>
* 列表数据类型
* @author Charles7c
* @since 2023/1/14 23:40
*/
@Data
@Accessors
(
chain
=
true
)
@Schema
(
description
=
"分页信息"
)
public
class
PageInfo
<
V
>
{
/**
* 列表数据
*/
@Schema
(
description
=
"列表数据"
)
private
List
<
V
>
list
;
/**
* 总记录数
*/
@Schema
(
description
=
"总记录数"
)
private
long
total
;
/**
* 基于 MyBatis Plus 分页数据构建分页信息,并将源数据转换为指定类型数据
*
* @param page
* MyBatis Plus 分页数据
* @param targetClass
* 目标类型 Class 对象
* @param <T>
* 源列表数据类型
* @param <V>
* 目标列表数据类型
* @return 分页信息
*/
public
static
<
T
,
V
>
PageInfo
<
V
>
build
(
IPage
<
T
>
page
,
Class
<
V
>
targetClass
)
{
if
(
page
==
null
)
{
return
null
;
}
PageInfo
<
V
>
pageInfo
=
new
PageInfo
<>();
pageInfo
.
setList
(
BeanUtil
.
copyToList
(
page
.
getRecords
(),
targetClass
));
pageInfo
.
setTotal
(
page
.
getTotal
());
return
pageInfo
;
}
/**
* 基于 MyBatis Plus 分页数据构建分页信息
*
* @param page
* MyBatis Plus 分页数据
* @param <V>
* 列表数据类型
* @return 分页信息
*/
public
static
<
V
>
PageInfo
<
V
>
build
(
IPage
<
V
>
page
)
{
if
(
page
==
null
)
{
return
null
;
}
PageInfo
<
V
>
pageInfo
=
new
PageInfo
<>();
pageInfo
.
setList
(
page
.
getRecords
());
pageInfo
.
setTotal
(
pageInfo
.
getTotal
());
return
pageInfo
;
}
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/R.java
浏览文件 @
f4ea2d44
...
...
@@ -16,7 +16,6 @@
package
top.charles7c.cnadmin.common.model.vo
;
import
java.io.Serializable
;
import
java.time.LocalDateTime
;
import
lombok.AccessLevel
;
...
...
@@ -36,9 +35,7 @@ import org.springframework.http.HttpStatus;
@Data
@NoArgsConstructor
(
access
=
AccessLevel
.
PRIVATE
)
@Schema
(
description
=
"响应信息"
)
public
class
R
<
V
extends
Serializable
>
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
public
class
R
<
V
>
{
/** 是否成功 */
@Schema
(
description
=
"是否成功"
)
...
...
@@ -72,39 +69,39 @@ public class R<V extends Serializable> implements Serializable {
this
.
data
=
data
;
}
public
static
<
V
extends
Serializable
>
R
<
V
>
ok
()
{
public
static
<
V
>
R
<
V
>
ok
()
{
return
new
R
<>(
true
,
SUCCESS_CODE
,
"操作成功"
,
null
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
ok
(
V
data
)
{
public
static
<
V
>
R
<
V
>
ok
(
V
data
)
{
return
new
R
<>(
true
,
SUCCESS_CODE
,
"操作成功"
,
data
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
ok
(
String
msg
)
{
public
static
<
V
>
R
<
V
>
ok
(
String
msg
)
{
return
new
R
<>(
true
,
SUCCESS_CODE
,
msg
,
null
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
ok
(
String
msg
,
V
data
)
{
public
static
<
V
>
R
<
V
>
ok
(
String
msg
,
V
data
)
{
return
new
R
<>(
true
,
SUCCESS_CODE
,
msg
,
data
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
fail
()
{
public
static
<
V
>
R
<
V
>
fail
()
{
return
new
R
<>(
false
,
FAIL_CODE
,
"操作失败"
,
null
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
fail
(
String
msg
)
{
public
static
<
V
>
R
<
V
>
fail
(
String
msg
)
{
return
new
R
<>(
false
,
FAIL_CODE
,
msg
,
null
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
fail
(
V
data
)
{
public
static
<
V
>
R
<
V
>
fail
(
V
data
)
{
return
new
R
<>(
false
,
FAIL_CODE
,
"操作失败"
,
data
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
fail
(
String
msg
,
V
data
)
{
public
static
<
V
>
R
<
V
>
fail
(
String
msg
,
V
data
)
{
return
new
R
<>(
false
,
FAIL_CODE
,
msg
,
data
);
}
public
static
<
V
extends
Serializable
>
R
<
V
>
fail
(
int
code
,
String
msg
)
{
public
static
<
V
>
R
<
V
>
fail
(
int
code
,
String
msg
)
{
return
new
R
<>(
false
,
code
,
msg
,
null
);
}
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/ReflectUtils.java
0 → 100644
浏览文件 @
f4ea2d44
/*
* 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.common.util
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Modifier
;
import
java.util.Arrays
;
import
lombok.AccessLevel
;
import
lombok.NoArgsConstructor
;
import
cn.hutool.core.util.ReflectUtil
;
/**
* 反射工具类
*
* @author Charles7c
* @since 2023/1/15 22:05
*/
@NoArgsConstructor
(
access
=
AccessLevel
.
PRIVATE
)
public
class
ReflectUtils
{
/**
* 获得一个类中所有非静态字段名列表,包括其父类中的字段<br>
* 如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后。
*
* @param beanClass
* 类
* @return 非静态字段名列表
* @throws SecurityException
* 安全检查异常
*/
public
static
String
[]
getNonStaticFieldsName
(
Class
<?>
beanClass
)
throws
SecurityException
{
Field
[]
nonStaticFields
=
getNonStaticFields
(
beanClass
);
return
Arrays
.
stream
(
nonStaticFields
).
map
(
Field:
:
getName
).
toArray
(
String
[]::
new
);
}
/**
* 获得一个类中所有非静态字段列表,包括其父类中的字段<br>
* 如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后。
*
* @param beanClass
* 类
* @return 非静态字段列表
* @throws SecurityException
* 安全检查异常
*/
public
static
Field
[]
getNonStaticFields
(
Class
<?>
beanClass
)
throws
SecurityException
{
Field
[]
fields
=
ReflectUtil
.
getFields
(
beanClass
);
return
Arrays
.
stream
(
fields
).
filter
(
f
->
!
Modifier
.
isStatic
(
f
.
getModifiers
())).
toArray
(
Field
[]::
new
);
}
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/helper/QueryHelper.java
0 → 100644
浏览文件 @
f4ea2d44
/*
* 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.common.util.helper
;
import
java.lang.reflect.Field
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
import
lombok.AccessLevel
;
import
lombok.NoArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.StrUtil
;
import
top.charles7c.cnadmin.common.annotation.Query
;
/**
* 查询助手
*
* @author Charles7c
* @since 2023/1/15 18:17
*/
@Slf4j
@NoArgsConstructor
(
access
=
AccessLevel
.
PRIVATE
)
public
class
QueryHelper
{
/**
* 根据查询条件构建 MyBatis Plus 查询条件封装对象
*
* @param query
* 查询条件
* @param <Q>
* 查询条件数据类型
* @param <R>
* 查询数据类型
* @return MyBatis Plus 查询条件封装对象
*/
public
static
<
Q
,
R
>
QueryWrapper
<
R
>
build
(
Q
query
)
{
QueryWrapper
<
R
>
queryWrapper
=
Wrappers
.
query
();
// 没有查询条件,直接返回
if
(
query
==
null
)
{
return
queryWrapper
;
}
// 获取查询条件中所有的属性(包括私有的和父类的)
List
<
Field
>
fieldList
=
getFieldList
(
query
.
getClass
(),
new
ArrayList
<>());
fieldList
.
forEach
(
field
->
buildQuery
(
query
,
field
,
queryWrapper
));
return
queryWrapper
;
}
/**
* 获取指定类的所有属性(包括私有的和父类的)
*
* @param clazz
* 指定类
* @param fieldList
* 属性列表
* @param <Q>
* 查询条件数据类型
* @return 属性列表(包括私有的和父类的)
*/
public
static
<
Q
>
List
<
Field
>
getFieldList
(
Class
<
Q
>
clazz
,
List
<
Field
>
fieldList
)
{
if
(
clazz
!=
null
)
{
fieldList
.
addAll
(
Arrays
.
asList
(
clazz
.
getDeclaredFields
()));
getFieldList
(
clazz
.
getSuperclass
(),
fieldList
);
}
return
fieldList
;
}
/**
* 构建 MyBatis Plus 查询条件封装对象
*
* @param query
* 查询条件
* @param field
* 属性
* @param queryWrapper
* MyBatis Plus 查询条件封装对象
* @param <Q>
* 查询条件数据类型
* @param <R>
* 查询数据类型
*/
private
static
<
Q
,
R
>
void
buildQuery
(
Q
query
,
Field
field
,
QueryWrapper
<
R
>
queryWrapper
)
{
boolean
accessible
=
field
.
isAccessible
();
try
{
field
.
setAccessible
(
true
);
// 没有 @Query,直接返回
Query
queryAnnotation
=
field
.
getAnnotation
(
Query
.
class
);
if
(
queryAnnotation
==
null
)
{
return
;
}
// 如果属性值为空,直接返回
Object
fieldValue
=
field
.
get
(
query
);
if
(
ObjectUtil
.
isEmpty
(
fieldValue
))
{
return
;
}
// 解析查询条件
parse
(
queryAnnotation
,
field
.
getName
(),
fieldValue
,
queryWrapper
);
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
}
finally
{
field
.
setAccessible
(
accessible
);
}
}
/**
* 解析查询条件
*
* @param queryAnnotation
* 查询注解
* @param fieldName
* 属性名
* @param fieldValue
* 属性值
* @param queryWrapper
* MyBatis Plus 查询条件封装对象
* @param <R>
* 查询数据类型
*/
private
static
<
R
>
void
parse
(
Query
queryAnnotation
,
String
fieldName
,
Object
fieldValue
,
QueryWrapper
<
R
>
queryWrapper
)
{
// 解析多属性模糊查询
// 如果设置了多属性模糊查询,分割属性进行条件拼接
String
blurry
=
queryAnnotation
.
blurry
();
if
(
StrUtil
.
isNotBlank
(
blurry
))
{
String
[]
propertyArr
=
blurry
.
split
(
","
);
queryWrapper
.
and
(
wrapper
->
{
for
(
String
property
:
propertyArr
)
{
wrapper
.
or
().
like
(
StrUtil
.
toUnderlineCase
(
property
),
fieldValue
);
}
});
return
;
}
// 解析单个属性查询
// 如果没有单独指定属性名,就和使用该注解的属性的名称一致
// 注意:数据库规范中列采用下划线连接法命名,程序规范中变量采用驼峰法命名
String
property
=
queryAnnotation
.
property
();
fieldName
=
StrUtil
.
isNotBlank
(
property
)
?
property
:
fieldName
;
String
columnName
=
StrUtil
.
toUnderlineCase
(
fieldName
);
switch
(
queryAnnotation
.
type
())
{
case
EQUAL:
queryWrapper
.
eq
(
columnName
,
fieldValue
);
break
;
case
NOT_EQUAL:
queryWrapper
.
ne
(
columnName
,
fieldValue
);
break
;
case
GREATER_THAN:
queryWrapper
.
gt
(
columnName
,
fieldValue
);
break
;
case
LESS_THAN:
queryWrapper
.
lt
(
columnName
,
fieldValue
);
break
;
case
GREATER_THAN_OR_EQUAL:
queryWrapper
.
ge
(
columnName
,
fieldValue
);
break
;
case
LESS_THAN_OR_EQUAL:
queryWrapper
.
le
(
columnName
,
fieldValue
);
break
;
case
BETWEEN:
List
<
Object
>
between
=
new
ArrayList
<>((
List
<
Object
>)
fieldValue
);
queryWrapper
.
between
(
columnName
,
between
.
get
(
0
),
between
.
get
(
1
));
break
;
case
LEFT_LIKE:
queryWrapper
.
likeLeft
(
columnName
,
fieldValue
);
break
;
case
INNER_LIKE:
queryWrapper
.
like
(
columnName
,
fieldValue
);
break
;
case
RIGHT_LIKE:
queryWrapper
.
likeRight
(
columnName
,
fieldValue
);
break
;
case
IN:
if
(
CollUtil
.
isNotEmpty
((
List
<
Object
>)
fieldValue
))
{
queryWrapper
.
in
(
columnName
,
(
List
<
Object
>)
fieldValue
);
}
break
;
case
NOT_IN:
if
(
CollUtil
.
isNotEmpty
((
List
<
Object
>)
fieldValue
))
{
queryWrapper
.
notIn
(
columnName
,
(
List
<
Object
>)
fieldValue
);
}
break
;
case
IS_NULL:
queryWrapper
.
isNull
(
columnName
);
break
;
case
NOT_NULL:
queryWrapper
.
isNotNull
(
columnName
);
break
;
default
:
break
;
}
}
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/holder/LogContextHolder.java
浏览文件 @
f4ea2d44
...
...
@@ -19,10 +19,10 @@ package top.charles7c.cnadmin.common.util.holder;
import
lombok.AccessLevel
;
import
lombok.NoArgsConstructor
;
import
top.charles7c.cnadmin.common.model.dto.
OperationLog
;
import
top.charles7c.cnadmin.common.model.dto.
LogContext
;
/**
*
操作
日志上下文持有者
*
系统
日志上下文持有者
*
* @author Charles7c
* @since 2022/12/25 8:55
...
...
@@ -30,29 +30,29 @@ import top.charles7c.cnadmin.common.model.dto.OperationLog;
@NoArgsConstructor
(
access
=
AccessLevel
.
PRIVATE
)
public
class
LogContextHolder
{
private
static
final
ThreadLocal
<
OperationLog
>
LOG_THREAD_LOCAL
=
new
ThreadLocal
<>();
private
static
final
ThreadLocal
<
LogContext
>
LOG_THREAD_LOCAL
=
new
ThreadLocal
<>();
/**
* 存储
操作日志
* 存储
系统日志上下文
*
* @param
operationLog
*
操作日志
信息
* @param
logContext
*
系统日志上下文
信息
*/
public
static
void
set
(
OperationLog
operationLog
)
{
LOG_THREAD_LOCAL
.
set
(
operationLog
);
public
static
void
set
(
LogContext
logContext
)
{
LOG_THREAD_LOCAL
.
set
(
logContext
);
}
/**
* 获取
操作日志
* 获取
系统日志上下文
*
* @return
操作日志
信息
* @return
系统日志上下文
信息
*/
public
static
OperationLog
get
()
{
public
static
LogContext
get
()
{
return
LOG_THREAD_LOCAL
.
get
();
}
/**
* 移除
操作日志
* 移除
系统日志上下文
*/
public
static
void
remove
()
{
LOG_THREAD_LOCAL
.
remove
();
...
...
continew-admin-monitor/pom.xml
浏览文件 @
f4ea2d44
...
...
@@ -32,10 +32,10 @@ limitations under the License.
<description>
系统监控模块(存放系统监控模块相关功能,例如:日志管理、服务监控等)
</description>
<dependencies>
<!--
公共模块(存放公共工具类,公共配置
等) -->
<!--
系统管理模块(存放系统管理模块相关功能,例如:部门管理、角色管理、用户管理
等) -->
<dependency>
<groupId>
top.charles7c
</groupId>
<artifactId>
continew-admin-
common
</artifactId>
<artifactId>
continew-admin-
system
</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/annotation/Log.java
浏览文件 @
f4ea2d44
...
...
@@ -19,7 +19,7 @@ package top.charles7c.cnadmin.monitor.annotation;
import
java.lang.annotation.*
;
/**
*
操作
日志注解(用于接口方法或类上)
*
系统
日志注解(用于接口方法或类上)
*
* @author Charles7c
* @since 2022/12/23 20:00
...
...
@@ -30,7 +30,7 @@ import java.lang.annotation.*;
public
@interface
Log
{
/**
*
操作
日志描述
* 日志描述
*/
String
value
()
default
""
;
...
...
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/config/properties/LogProperties.java
浏览文件 @
f4ea2d44
...
...
@@ -25,28 +25,33 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import
org.springframework.stereotype.Component
;
/**
*
操作
日志配置属性
*
系统
日志配置属性
*
* @author Charles7c
* @since 2022/12/24 23:04
*/
@Data
@Component
@ConfigurationProperties
(
prefix
=
"logging.
operation
"
)
@ConfigurationProperties
(
prefix
=
"logging.
system
"
)
public
class
LogProperties
{
/**
* 是否启用
操作
日志
* 是否启用
系统
日志
*/
private
Boolean
enabled
=
false
;
private
Boolean
enabled
;
/**
*
脱敏字段
*
是否记录内网 IP 操作
*/
private
List
<
String
>
desensitize
=
new
ArrayList
<>()
;
private
Boolean
includeInnerIp
;
/**
*
不记录操作日志的请求方式
*
哪些请求方式不记录系统日志
*/
private
List
<
String
>
excludeMethods
=
new
ArrayList
<>();
/**
* 脱敏字段
*/
private
List
<
String
>
desensitize
=
new
ArrayList
<>();
}
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/enums/Log
Level
Enum.java
→
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/enums/Log
Result
Enum.java
浏览文件 @
f4ea2d44
...
...
@@ -19,22 +19,24 @@ package top.charles7c.cnadmin.monitor.enums;
import
lombok.Getter
;
import
lombok.RequiredArgsConstructor
;
import
com.baomidou.mybatisplus.annotation.IEnum
;
/**
* 操作
日志级别
枚举
* 操作
结果
枚举
*
* @author Charles7c
* @since 2022/12/25 9:09
*/
@Getter
@RequiredArgsConstructor
public
enum
Log
LevelEnum
{
public
enum
Log
ResultEnum
implements
IEnum
<
Integer
>
{
/**
普通
*/
INFO
(
"普通
"
),
/**
成功
*/
SUCCESS
(
1
,
"成功
"
),
/**
错误
*/
ERROR
(
"错误
"
),;
/**
失败
*/
FAILURE
(
2
,
"失败
"
),;
/** 描述 */
private
final
Integer
value
;
private
final
String
description
;
}
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/interceptor/LogInterceptor.java
浏览文件 @
f4ea2d44
...
...
@@ -42,20 +42,21 @@ import cn.hutool.core.exceptions.ExceptionUtil;
import
cn.hutool.core.util.StrUtil
;
import
cn.hutool.extra.servlet.ServletUtil
;
import
cn.hutool.extra.spring.SpringUtil
;
import
cn.hutool.http.HttpStatus
;
import
cn.hutool.json.JSONUtil
;
import
top.charles7c.cnadmin.common.model.dto.
OperationLog
;
import
top.charles7c.cnadmin.common.model.dto.
LogContext
;
import
top.charles7c.cnadmin.common.util.IpUtils
;
import
top.charles7c.cnadmin.common.util.ServletUtils
;
import
top.charles7c.cnadmin.common.util.helper.LoginHelper
;
import
top.charles7c.cnadmin.common.util.holder.LogContextHolder
;
import
top.charles7c.cnadmin.monitor.annotation.Log
;
import
top.charles7c.cnadmin.monitor.config.properties.LogProperties
;
import
top.charles7c.cnadmin.monitor.enums.Log
Level
Enum
;
import
top.charles7c.cnadmin.monitor.enums.Log
Result
Enum
;
import
top.charles7c.cnadmin.monitor.model.entity.SysLog
;
/**
*
操作
日志拦截器
*
系统
日志拦截器
*
* @author Charles7c
* @since 2022/12/24 21:14
...
...
@@ -87,14 +88,14 @@ public class LogInterceptor implements HandlerInterceptor {
return
;
}
// 记录描述
// 记录
日志
描述
this
.
logDescription
(
sysLog
,
handler
);
// 记录请求信息
this
.
logRequest
(
sysLog
,
request
);
// 记录响应信息
this
.
logResponse
(
sysLog
,
response
);
// 保存
操作
日志
// 保存
系统
日志
SpringUtil
.
getApplicationContext
().
publishEvent
(
sysLog
);
}
...
...
@@ -102,31 +103,31 @@ public class LogInterceptor implements HandlerInterceptor {
* 记录操作时间
*/
private
void
logCreateTime
()
{
OperationLog
operationLog
=
new
OperationLog
();
operationLog
.
setCreateUser
(
LoginHelper
.
getUserId
());
operationLog
.
setCreateTime
(
LocalDateTime
.
now
());
LogContextHolder
.
set
(
operationLog
);
LogContext
logContext
=
new
LogContext
();
logContext
.
setCreateUser
(
LoginHelper
.
getUserId
());
logContext
.
setCreateTime
(
LocalDateTime
.
now
());
LogContextHolder
.
set
(
logContext
);
}
/**
* 记录请求耗时及异常信息
*
* @return 日志信息
* @return
系统
日志信息
*/
private
SysLog
logElapsedTimeAndException
()
{
OperationLog
operationLog
=
LogContextHolder
.
get
();
if
(
operationLog
!=
null
)
{
LogContext
logContext
=
LogContextHolder
.
get
();
if
(
logContext
!=
null
)
{
LogContextHolder
.
remove
();
SysLog
sysLog
=
new
SysLog
();
sysLog
.
setCreateTime
(
operationLog
.
getCreateTime
());
sysLog
.
setCreateTime
(
logContext
.
getCreateTime
());
sysLog
.
setElapsedTime
(
System
.
currentTimeMillis
()
-
LocalDateTimeUtil
.
toEpochMilli
(
sysLog
.
getCreateTime
()));
sysLog
.
set
LogLevel
(
LogLevelEnum
.
INFO
);
sysLog
.
set
Result
(
LogResultEnum
.
SUCCESS
);
// 记录异常信息
Exception
exception
=
operationLog
.
getException
();
Exception
exception
=
logContext
.
getException
();
if
(
exception
!=
null
)
{
sysLog
.
set
LogLevel
(
LogLevelEnum
.
ERROR
);
sysLog
.
setException
(
ExceptionUtil
.
stacktraceToString
(
operationLog
.
getException
()
,
-
1
));
sysLog
.
set
Result
(
LogResultEnum
.
FAILURE
);
sysLog
.
setException
(
ExceptionUtil
.
stacktraceToString
(
exception
,
-
1
));
}
return
sysLog
;
}
...
...
@@ -137,7 +138,7 @@ public class LogInterceptor implements HandlerInterceptor {
* 记录日志描述
*
* @param sysLog
* 日志信息
*
系统
日志信息
* @param handler
* 处理器
*/
...
...
@@ -148,7 +149,7 @@ public class LogInterceptor implements HandlerInterceptor {
if
(
methodOperation
!=
null
)
{
sysLog
.
setDescription
(
StrUtil
.
isNotBlank
(
methodOperation
.
summary
())
?
methodOperation
.
summary
()
:
"请在该接口方法上指定
操作
日志描述"
);
StrUtil
.
isNotBlank
(
methodOperation
.
summary
())
?
methodOperation
.
summary
()
:
"请在该接口方法上指定日志描述"
);
}
// 例如:@Log("获取验证码") -> 获取验证码
if
(
methodLog
!=
null
&&
StrUtil
.
isNotBlank
(
methodLog
.
value
()))
{
...
...
@@ -160,7 +161,7 @@ public class LogInterceptor implements HandlerInterceptor {
* 记录请求信息
*
* @param sysLog
* 日志信息
*
系统
日志信息
* @param request
* 请求对象
*/
...
...
@@ -184,18 +185,21 @@ public class LogInterceptor implements HandlerInterceptor {
* 记录响应信息
*
* @param sysLog
* 日志信息
*
系统
日志信息
* @param response
* 响应对象
*/
private
void
logResponse
(
SysLog
sysLog
,
HttpServletResponse
response
)
{
sysLog
.
setStatusCode
(
response
.
getStatus
());
int
status
=
response
.
getStatus
();
sysLog
.
setStatusCode
(
status
);
sysLog
.
setResponseHeader
(
this
.
desensitize
(
ServletUtil
.
getHeadersMap
(
response
)));
// 响应体(不记录非 JSON 响应数据)
String
responseBody
=
this
.
getResponseBody
(
response
);
if
(
StrUtil
.
isNotBlank
(
responseBody
)
&&
JSONUtil
.
isTypeJSON
(
responseBody
))
{
sysLog
.
setResponseBody
(
responseBody
);
}
// 操作失败:>= 400
sysLog
.
setResult
(
status
>=
HttpStatus
.
HTTP_BAD_REQUEST
?
LogResultEnum
.
FAILURE
:
sysLog
.
getResult
());
}
/**
...
...
@@ -258,7 +262,7 @@ public class LogInterceptor implements HandlerInterceptor {
}
/**
* 检查是否要记录
操作
日志
* 检查是否要记录
系统
日志
*
* @param handler
* /
...
...
@@ -267,28 +271,34 @@ public class LogInterceptor implements HandlerInterceptor {
* @return true 需要记录,false 不需要记录
*/
private
boolean
checkIsNeedRecord
(
Object
handler
,
HttpServletRequest
request
)
{
// 1、未启用时,不需要记录
操作
日志
// 1、未启用时,不需要记录
系统
日志
if
(!(
handler
instanceof
HandlerMethod
)
||
Boolean
.
FALSE
.
equals
(
operationLogProperties
.
getEnabled
()))
{
return
false
;
}
// 2、排除不需要记录日志的接口
// 2、检查是否需要记录内网 IP 操作
boolean
isInnerIp
=
IpUtils
.
isInnerIP
(
ServletUtil
.
getClientIP
(
request
));
if
(
isInnerIp
&&
Boolean
.
FALSE
.
equals
(
operationLogProperties
.
getIncludeInnerIp
()))
{
return
false
;
}
// 3、排除不需要记录系统日志的接口
HandlerMethod
handlerMethod
=
(
HandlerMethod
)
handler
;
Log
methodLog
=
AnnotationUtils
.
findAnnotation
(
handlerMethod
.
getMethod
(),
Log
.
class
);
//
2.1 请求方式不要求记录且请求上没有 @Log 注解,则不记录操作
日志
//
3.1 请求方式不要求记录且请求上没有 @Log 注解,则不记录系统
日志
if
(
operationLogProperties
.
getExcludeMethods
().
contains
(
request
.
getMethod
())
&&
methodLog
==
null
)
{
return
false
;
}
//
2.2 如果接口上既没有 @Log 注解,也没有 @Operation 注解,则不记录操作
日志
//
3.2 如果接口上既没有 @Log 注解,也没有 @Operation 注解,则不记录系统
日志
Operation
methodOperation
=
AnnotationUtils
.
findAnnotation
(
handlerMethod
.
getMethod
(),
Operation
.
class
);
if
(
methodLog
==
null
&&
methodOperation
==
null
)
{
return
false
;
}
//
2.3 如果接口被隐藏,不记录操作
日志
//
3.3 如果接口被隐藏,不记录系统
日志
if
(
methodOperation
!=
null
&&
methodOperation
.
hidden
())
{
return
false
;
}
//
2.4 如果接口上有 @Log 注解,但是要求忽略该接口,则不记录操作
日志
//
3.4 如果接口上有 @Log 注解,但是要求忽略该接口,则不记录系统
日志
return
methodLog
==
null
||
!
methodLog
.
ignore
();
}
}
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/mapper/LogMapper.java
浏览文件 @
f4ea2d44
...
...
@@ -21,7 +21,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import
top.charles7c.cnadmin.monitor.model.entity.SysLog
;
/**
*
操作
日志 Mapper
*
系统
日志 Mapper
*
* @author Charles7c
* @since 2022/12/22 21:47
...
...
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/entity/SysLog.java
浏览文件 @
f4ea2d44
...
...
@@ -24,10 +24,10 @@ import lombok.Data;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
top.charles7c.cnadmin.monitor.enums.Log
Level
Enum
;
import
top.charles7c.cnadmin.monitor.enums.Log
Result
Enum
;
/**
*
操作
日志实体
*
系统
日志实体
*
* @author Charles7c
* @since 2022/12/25 9:11
...
...
@@ -44,18 +44,13 @@ public class SysLog implements Serializable {
@TableId
private
Long
logId
;
/**
* 日志级别
*/
private
LogLevelEnum
logLevel
;
/**
* 日志描述
*/
private
String
description
;
/**
* 请求
URL
* 请求URL
*/
private
String
requestUrl
;
...
...
@@ -95,12 +90,17 @@ public class SysLog implements Serializable {
private
Long
elapsedTime
;
/**
* 请求IP
* 操作结果(1成功 2失败)
*/
private
LogResultEnum
result
;
/**
* 操作IP
*/
private
String
requestIp
;
/**
* 操作地
址
* 操作地
点
*/
private
String
location
;
...
...
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/query/OperationLogQuery.java
0 → 100644
浏览文件 @
f4ea2d44
/*
* 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
static
top
.
charles7c
.
cnadmin
.
common
.
annotation
.
Query
.
Type
;
import
java.io.Serializable
;
import
lombok.Data
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
org.springdoc.api.annotations.ParameterObject
;
import
top.charles7c.cnadmin.common.annotation.Query
;
/**
* 操作日志查询条件
*
* @author Charles7c
* @since 2023/1/15 11:43
*/
@Data
@ParameterObject
@Schema
(
description
=
"操作日志查询条件"
)
public
class
OperationLogQuery
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 操作人
*/
@Schema
(
description
=
"操作人"
)
@Query
(
property
=
"createUser"
,
type
=
Type
.
EQUAL
)
private
Long
uid
;
}
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/model/vo/OperationLogVO.java
0 → 100644
浏览文件 @
f4ea2d44
/*
* 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
;
import
com.fasterxml.jackson.annotation.JsonIgnore
;
import
top.charles7c.cnadmin.monitor.enums.LogResultEnum
;
/**
* 操作日志信息
*
* @author Charles7c
* @since 2023/1/14 18:27
*/
@Data
@Schema
(
description
=
"操作日志信息"
)
public
class
OperationLogVO
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 日志ID
*/
@Schema
(
description
=
"日志ID"
)
private
Long
logId
;
/**
* 操作内容
*/
@Schema
(
description
=
"操作内容"
)
private
String
description
;
/**
* 操作结果(1成功 2失败)
*/
@Schema
(
description
=
"操作结果(1成功 2失败)"
,
type
=
"Integer"
,
allowableValues
=
{
"1"
,
"2"
})
private
LogResultEnum
result
;
/**
* 操作IP
*/
@Schema
(
description
=
"操作IP"
)
private
String
requestIp
;
/**
* 操作地点
*/
@Schema
(
description
=
"操作地点"
)
private
String
location
;
/**
* 浏览器
*/
@Schema
(
description
=
"浏览器"
)
private
String
browser
;
/**
* 操作人
*/
@JsonIgnore
private
Long
createUser
;
/**
* 操作人
*/
@Schema
(
description
=
"操作人"
)
private
String
createUserString
;
/**
* 操作时间
*/
@Schema
(
description
=
"操作时间"
)
private
LocalDateTime
createTime
;
}
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/service/LogService.java
浏览文件 @
f4ea2d44
...
...
@@ -17,7 +17,7 @@
package
top.charles7c.cnadmin.monitor.service
;
/**
*
操作
日志业务接口
*
系统
日志业务接口
*
* @author Charles7c
* @since 2022/12/23 20:12
...
...
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/service/OperationLogService.java
0 → 100644
浏览文件 @
f4ea2d44
/*
* 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.service
;
import
top.charles7c.cnadmin.common.model.query.PageQuery
;
import
top.charles7c.cnadmin.common.model.vo.PageInfo
;
import
top.charles7c.cnadmin.monitor.model.query.OperationLogQuery
;
import
top.charles7c.cnadmin.monitor.model.vo.OperationLogVO
;
/**
* 操作日志业务接口
*
* @author Charles7c
* @since 2023/1/15 21:05
*/
public
interface
OperationLogService
{
/**
* 分页查询列表
*
* @param query
* 查询条件
* @param pageQuery
* 分页查询条件
* @return 分页信息
*/
PageInfo
<
OperationLogVO
>
list
(
OperationLogQuery
query
,
PageQuery
pageQuery
);
}
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/service/impl/LogServiceImpl.java
浏览文件 @
f4ea2d44
...
...
@@ -28,7 +28,7 @@ import top.charles7c.cnadmin.monitor.model.entity.SysLog;
import
top.charles7c.cnadmin.monitor.service.LogService
;
/**
*
操作
日志业务实现类
*
系统
日志业务实现类
*
* @author Charles7c
* @since 2022/12/23 20:12
...
...
continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/service/impl/OperationLogServiceImpl.java
0 → 100644
浏览文件 @
f4ea2d44
/*
* 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.service.impl
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.stream.Collectors
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Service
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
cn.hutool.core.util.StrUtil
;
import
top.charles7c.cnadmin.common.model.query.PageQuery
;
import
top.charles7c.cnadmin.common.model.vo.PageInfo
;
import
top.charles7c.cnadmin.common.util.ReflectUtils
;
import
top.charles7c.cnadmin.common.util.helper.QueryHelper
;
import
top.charles7c.cnadmin.monitor.mapper.LogMapper
;
import
top.charles7c.cnadmin.monitor.model.entity.SysLog
;
import
top.charles7c.cnadmin.monitor.model.query.OperationLogQuery
;
import
top.charles7c.cnadmin.monitor.model.vo.OperationLogVO
;
import
top.charles7c.cnadmin.monitor.service.OperationLogService
;
import
top.charles7c.cnadmin.system.mapper.UserMapper
;
import
top.charles7c.cnadmin.system.model.entity.SysUser
;
/**
* 操作日志业务实现类
*
* @author Charles7c
* @since 2023/1/15 21:05
*/
@Slf4j
@Service
@RequiredArgsConstructor
public
class
OperationLogServiceImpl
implements
OperationLogService
{
private
final
LogMapper
logMapper
;
private
final
UserMapper
userMapper
;
@Override
public
PageInfo
<
OperationLogVO
>
list
(
OperationLogQuery
query
,
PageQuery
pageQuery
)
{
QueryWrapper
<
SysLog
>
queryWrapper
=
QueryHelper
.
build
(
query
);
// 限定查询信息
String
[]
fieldsName
=
ReflectUtils
.
getNonStaticFieldsName
(
OperationLogVO
.
class
);
List
<
String
>
columns
=
Arrays
.
stream
(
fieldsName
).
map
(
StrUtil:
:
toUnderlineCase
)
.
filter
(
n
->
!
n
.
endsWith
(
"string"
)).
collect
(
Collectors
.
toList
());
queryWrapper
.
select
(
columns
);
// 分页查询
IPage
<
SysLog
>
page
=
logMapper
.
selectPage
(
pageQuery
.
toPage
(),
queryWrapper
);
PageInfo
<
OperationLogVO
>
pageInfo
=
PageInfo
.
build
(
page
,
OperationLogVO
.
class
);
pageInfo
.
getList
().
forEach
(
this
::
fill
);
return
pageInfo
;
}
/**
* 填充数据
*
* @param vo
* VO
*/
private
void
fill
(
OperationLogVO
vo
)
{
Long
createUser
=
vo
.
getCreateUser
();
if
(
createUser
==
null
)
{
return
;
}
SysUser
sysUser
=
userMapper
.
selectById
(
createUser
);
vo
.
setCreateUserString
(
sysUser
.
getNickname
());
}
}
continew-admin-ui/src/api/monitor/operation-log.ts
0 → 100644
浏览文件 @
f4ea2d44
import
axios
from
'
axios
'
;
import
qs
from
'
query-string
'
;
export
interface
OperationLogRecord
{
logId
:
string
;
description
:
string
;
result
:
number
,
requestIp
:
string
,
location
:
string
,
browser
:
string
,
createUserString
:
string
;
createTime
:
string
;
}
export
interface
OperationLogParams
extends
Partial
<
OperationLogRecord
>
{
page
:
number
;
size
:
number
;
sort
:
Array
<
string
>
;
uid
:
string
;
}
export
interface
OperationLogListRes
{
list
:
OperationLogRecord
[];
total
:
number
;
}
export
function
queryOperationLogList
(
params
:
OperationLogParams
)
{
return
axios
.
get
<
OperationLogListRes
>
(
'
/monitor/log/operation
'
,
{
params
,
paramsSerializer
:
(
obj
)
=>
{
return
qs
.
stringify
(
obj
);
},
});
}
\ No newline at end of file
continew-admin-ui/src/assets/style/global.less
浏览文件 @
f4ea2d44
...
...
@@ -90,5 +90,8 @@ body {
&.pass {
background-color: rgb(var(--green-6));
}
&.fail {
background-color: rgb(var(--red-6));
}
}
}
continew-admin-ui/src/store/modules/login/index.ts
浏览文件 @
f4ea2d44
...
...
@@ -13,7 +13,7 @@ import useAppStore from '../app';
const
useLoginStore
=
defineStore
(
'
user
'
,
{
state
:
():
UserState
=>
({
userId
:
1
,
userId
:
''
,
username
:
''
,
nickname
:
''
,
gender
:
0
,
...
...
continew-admin-ui/src/store/modules/login/types.ts
浏览文件 @
f4ea2d44
export
type
RoleType
=
''
|
'
*
'
|
'
admin
'
|
'
user
'
;
export
interface
UserState
{
userId
:
number
;
userId
:
string
;
username
:
string
;
nickname
:
string
;
gender
:
number
;
...
...
continew-admin-ui/src/views/login/components/login-form.vue
浏览文件 @
f4ea2d44
...
...
@@ -133,7 +133,7 @@
captchaImgBase64
.
value
=
data
.
img
}
onMounted
(()
=>
{
getCaptcha
()
getCaptcha
()
;
})
// 记住我
...
...
continew-admin-ui/src/views/system/user/center/components/operation-log.vue
0 → 100644
浏览文件 @
f4ea2d44
<
template
>
<div
class=
"container"
>
<a-table
row-key=
"id"
:loading=
"loading"
:pagination=
"pagination"
:columns=
"columns"
:data=
"renderData"
:bordered=
"false"
size=
"large"
@
page-change=
"onPageChange"
>
<template
#index
="
{ rowIndex }">
{{
rowIndex
+
1
+
(
pagination
.
current
-
1
)
*
pagination
.
pageSize
}}
</
template
>
<
template
#result=
"{ record }"
>
<a-space
v-if=
"record.result === 1"
>
<a-tag
color=
"green"
>
<span
class=
"circle pass"
></span>
成功
</a-tag>
</a-space>
<a-space
v-else
>
<a-tag
color=
"red"
>
<span
class=
"circle fail"
></span>
失败
</a-tag>
</a-space>
</
template
>
<
template
#pagination-left
>
<a-tooltip
content=
"刷新"
>
<div
class=
"action-icon"
@
click=
"onRefresh"
>
<icon-refresh
size=
"18"
/>
</div>
</a-tooltip>
</
template
>
</a-table>
</div>
</template>
<
script
lang=
"ts"
setup
>
import
{
computed
,
ref
,
reactive
}
from
"
vue
"
;
import
{
useLoginStore
}
from
'
@/store
'
;
import
useLoading
from
'
@/hooks/loading
'
;
import
{
queryOperationLogList
,
OperationLogRecord
,
OperationLogParams
}
from
'
@/api/monitor/operation-log
'
;
import
{
Pagination
}
from
'
@/types/global
'
;
import
type
{
TableColumnData
}
from
'
@arco-design/web-vue/es/table/interface
'
;
const
{
loading
,
setLoading
}
=
useLoading
(
true
);
const
loginStore
=
useLoginStore
();
const
renderData
=
ref
<
OperationLogRecord
[]
>
([]);
const
basePagination
:
Pagination
=
{
current
:
1
,
pageSize
:
10
,
};
const
pagination
=
reactive
({
...
basePagination
,
});
const
columns
=
computed
<
TableColumnData
[]
>
(()
=>
[
{
title
:
'
序号
'
,
dataIndex
:
'
index
'
,
slotName
:
'
index
'
,
},
{
title
:
'
操作时间
'
,
dataIndex
:
'
createTime
'
,
},
{
title
:
'
操作内容
'
,
dataIndex
:
'
description
'
,
},
{
title
:
'
操作结果
'
,
dataIndex
:
'
result
'
,
slotName
:
'
result
'
,
},
{
title
:
'
操作IP
'
,
dataIndex
:
'
requestIp
'
,
},
{
title
:
'
操作地点
'
,
dataIndex
:
'
location
'
,
},
{
title
:
'
浏览器
'
,
dataIndex
:
'
browser
'
,
},
]);
const
fetchData
=
async
(
params
:
OperationLogParams
=
{
uid
:
loginStore
.
userId
,
page
:
1
,
size
:
10
,
sort
:
[
'
createTime,desc
'
]
}
)
=>
{
setLoading
(
true
);
try
{
const
{
data
}
=
await
queryOperationLogList
(
params
);
renderData
.
value
=
data
.
list
;
pagination
.
current
=
params
.
page
;
pagination
.
total
=
data
.
total
;
}
catch
(
err
)
{
// you can report use errorHandler or other
}
finally
{
setLoading
(
false
);
}
};
const
onPageChange
=
(
current
:
number
)
=>
{
fetchData
({
uid
:
loginStore
.
userId
,
page
:
current
,
size
:
pagination
.
pageSize
,
sort
:
[
'
createTime,desc
'
]
});
};
const
onRefresh
=
()
=>
{
fetchData
({
uid
:
loginStore
.
userId
,
page
:
pagination
.
current
,
size
:
pagination
.
pageSize
,
sort
:
[
'
createTime,desc
'
],
}
as
unknown
as
OperationLogParams
);
};
fetchData
();
</
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;
}
}
}
.action-icon {
cursor: pointer;
}
.action-icon:hover {
color: #0960bd;
}
</
style
>
continew-admin-ui/src/views/system/user/center/index.vue
浏览文件 @
f4ea2d44
...
...
@@ -15,6 +15,9 @@
<a-tab-pane
key=
"2"
:title=
"$t('userCenter.tab.securitySettings')"
>
<SecuritySettings
/>
</a-tab-pane>
<a-tab-pane
key=
"3"
:title=
"$t('userCenter.tab.operationLog')"
>
<OperationLog
/>
</a-tab-pane>
</a-tabs>
</a-col>
</a-row>
...
...
@@ -25,6 +28,7 @@
import
UserPanel
from
'
./components/user-panel.vue
'
;
import
BasicInfo
from
'
./components/basic-info.vue
'
;
import
SecuritySettings
from
'
./components/security-settings.vue
'
;
import
OperationLog
from
'
./components/operation-log.vue
'
;
</
script
>
<
script
lang=
"ts"
>
...
...
continew-admin-ui/src/views/system/user/center/locale/en-US.ts
浏览文件 @
f4ea2d44
...
...
@@ -2,6 +2,7 @@ export default {
'
menu.user.center
'
:
'
User Center
'
,
'
userCenter.tab.basicInfo
'
:
'
Basic Information
'
,
'
userCenter.tab.securitySettings
'
:
'
Security Settings
'
,
'
userCenter.tab.operationLog
'
:
'
Operation Log
'
,
// user-panel
'
userCenter.panel.avatar
'
:
'
Avatar
'
,
...
...
continew-admin-ui/src/views/system/user/center/locale/zh-CN.ts
浏览文件 @
f4ea2d44
...
...
@@ -2,6 +2,7 @@ export default {
'
menu.user.center
'
:
'
个人中心
'
,
'
userCenter.tab.basicInfo
'
:
'
基础信息
'
,
'
userCenter.tab.securitySettings
'
:
'
安全设置
'
,
'
userCenter.tab.operationLog
'
:
'
操作日志
'
,
// user-panel
'
userCenter.panel.avatar
'
:
'
头像
'
,
...
...
continew-admin-webapi/pom.xml
浏览文件 @
f4ea2d44
...
...
@@ -49,12 +49,6 @@ limitations under the License.
<groupId>
top.charles7c
</groupId>
<artifactId>
continew-admin-monitor
</artifactId>
</dependency>
<!-- 系统管理模块(存放系统管理模块相关功能,例如:部门管理、角色管理、用户管理等) -->
<dependency>
<groupId>
top.charles7c
</groupId>
<artifactId>
continew-admin-system
</artifactId>
</dependency>
</dependencies>
<build>
...
...
continew-admin-webapi/src/main/java/top/charles7c/cnadmin/webapi/controller/monitor/OperationLogController.java
0 → 100644
浏览文件 @
f4ea2d44
/*
* 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
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.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
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.monitor.model.query.OperationLogQuery
;
import
top.charles7c.cnadmin.monitor.model.vo.OperationLogVO
;
import
top.charles7c.cnadmin.monitor.service.OperationLogService
;
/**
* 操作日志 API
*
* @author Charles7c
* @since 2023/1/14 18:09
*/
@Tag
(
name
=
"操作日志 API"
)
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping
(
value
=
"/monitor/log/operation"
,
produces
=
MediaType
.
APPLICATION_JSON_VALUE
)
public
class
OperationLogController
{
private
final
OperationLogService
operationLogService
;
@Operation
(
summary
=
"分页查询操作日志列表"
)
@GetMapping
public
R
<
PageInfo
<
OperationLogVO
>>
list
(
@Validated
OperationLogQuery
query
,
@Validated
PageQuery
pageQuery
)
{
PageInfo
<
OperationLogVO
>
pageInfo
=
operationLogService
.
list
(
query
,
pageQuery
);
return
R
.
ok
(
pageInfo
);
}
}
continew-admin-webapi/src/main/resources/application.yml
浏览文件 @
f4ea2d44
...
...
@@ -20,7 +20,7 @@ continew-admin:
name
:
Apache-2.0
url
:
https://github.com/Charles7c/continew-admin/blob/dev/LICENSE
# 是否本地解析 IP 归属地
ipAddrLocalParseEnabled
:
fals
e
ipAddrLocalParseEnabled
:
tru
e
---
### 日志配置(重叠部分,优先级高于 logback-spring.xml 中的配置)
logging
:
...
...
@@ -29,11 +29,13 @@ logging:
file
:
path
:
@
logging.file.path@
config
:
classpath:logback-spring.xml
##
操作
日志配置
operation
:
# 是否启用
操作
日志
##
系统
日志配置
system
:
# 是否启用
系统
日志
enabled
:
true
# 不记录操作日志的请求方式
# 是否记录内网 IP 操作
includeInnerIp
:
false
# 哪些请求方式不记录系统日志
#excludeMethods:
# - GET
# 脱敏字段
...
...
continew-admin-webapi/src/main/resources/db/changelog/v0.0.1/continew-admin_table.sql
浏览文件 @
f4ea2d44
...
...
@@ -26,7 +26,6 @@ CREATE TABLE IF NOT EXISTS `sys_user` (
CREATE
TABLE
IF
NOT
EXISTS
`sys_log`
(
`log_id`
bigint
(
20
)
unsigned
AUTO_INCREMENT
COMMENT
'日志ID'
,
`log_level`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'日志级别'
,
`description`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'日志描述'
,
`request_url`
varchar
(
512
)
NOT
NULL
DEFAULT
''
COMMENT
'请求URL'
,
`request_method`
varchar
(
10
)
DEFAULT
NULL
COMMENT
'请求方式'
,
...
...
@@ -34,14 +33,15 @@ CREATE TABLE IF NOT EXISTS `sys_log` (
`request_body`
text
DEFAULT
NULL
COMMENT
'请求体'
,
`status_code`
int
(
11
)
unsigned
DEFAULT
NULL
COMMENT
'状态码'
,
`response_header`
text
DEFAULT
NULL
COMMENT
'响应头'
,
`response_body`
text
DEFAULT
NULL
COMMENT
'响应体'
,
`response_body`
medium
text
DEFAULT
NULL
COMMENT
'响应体'
,
`elapsed_time`
bigint
(
20
)
unsigned
DEFAULT
NULL
COMMENT
'请求耗时(ms)'
,
`request_ip`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'请求IP'
,
`location`
varchar
(
512
)
DEFAULT
NULL
COMMENT
'操作地址'
,
`result`
tinyint
(
1
)
unsigned
DEFAULT
1
COMMENT
'操作结果(1成功 2失败)'
,
`request_ip`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'操作IP'
,
`location`
varchar
(
512
)
DEFAULT
NULL
COMMENT
'操作地点'
,
`browser`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'浏览器'
,
`exception`
text
DEFAULT
NULL
COMMENT
'异常'
,
`exception`
medium
text
DEFAULT
NULL
COMMENT
'异常'
,
`create_user`
bigint
(
20
)
unsigned
DEFAULT
NULL
COMMENT
'操作人'
,
`create_time`
datetime
NOT
NULL
COMMENT
'操作时间'
,
PRIMARY
KEY
(
`log_id`
)
USING
BTREE
,
INDEX
`idx_createUser`
(
`create_user`
)
USING
BTREE
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'
操作
日志表'
;
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'
系统
日志表'
;
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录