添加操作关系信息查看
This commit is contained in:
+27
@@ -10,8 +10,11 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import xtools.app.sys.model.dto.excel.SysOptLogExcel;
|
||||
import xtools.app.sys.model.dto.req.SysOptLogAccountReq;
|
||||
import xtools.app.sys.model.dto.req.SysOptLogPageReq;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogAccountResp;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogResp;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogTitleTreeResp;
|
||||
import xtools.app.sys.service.SysOptLogService;
|
||||
import xtools.boot.api.exection.BizError;
|
||||
import xtools.boot.api.model.dto.Result;
|
||||
@@ -61,4 +64,28 @@ public class SysOptLogController {
|
||||
HttpServletUtils.addDownloadHeader(response, filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取操作账号列表
|
||||
*
|
||||
* @param req 请求参数(时间范围)
|
||||
* @return 操作账号列表
|
||||
*/
|
||||
@Operation(summary = "获取操作账号列表")
|
||||
@PostMapping("get-account-list")
|
||||
public Result<List<SysOptLogAccountResp>> getAccountList(@RequestBody @Valid SysOptLogAccountReq req) {
|
||||
return sysOptLogService.getAccountList(req);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取操作统计树
|
||||
*
|
||||
* @param req 请求参数(账号ID,时间范围)
|
||||
* @return 操作统计树
|
||||
*/
|
||||
@Operation(summary = "获取操作统计树")
|
||||
@PostMapping("get-opt-tree")
|
||||
public Result<SysOptLogTitleTreeResp> getOptTree(@RequestBody @Valid SysOptLogAccountReq req) {
|
||||
return sysOptLogService.getOptTree(req);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+32
@@ -2,8 +2,14 @@ package xtools.app.sys.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogAccountResp;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogTitleCountResp;
|
||||
import xtools.app.sys.model.entity.SysOptLog;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLogMapper</p>
|
||||
* <p>Description : 系统操作日志 Mapper 接口</p>
|
||||
@@ -16,4 +22,30 @@ import xtools.app.sys.model.entity.SysOptLog;
|
||||
@Mapper
|
||||
public interface SysOptLogMapper extends BaseMapper<SysOptLog> {
|
||||
|
||||
/**
|
||||
* 获取操作账号列表
|
||||
*
|
||||
* @param startTime 开始时间(包含)
|
||||
* @param endTime 结束时间(包含)
|
||||
* @return 操作账号列表
|
||||
*/
|
||||
List<SysOptLogAccountResp> getOptAccountList(
|
||||
@Param("startTime") Instant startTime,
|
||||
@Param("endTime") Instant endTime
|
||||
);
|
||||
|
||||
/**
|
||||
* 获取该账号的操作日志
|
||||
*
|
||||
* @param accountId 账号ID
|
||||
* @param startTime 开始时间(包含)
|
||||
* @param endTime 结束时间(包含)
|
||||
* @return 操作日志
|
||||
*/
|
||||
List<SysOptLogTitleCountResp> getOptCount(
|
||||
@Param("accountId") Long accountId,
|
||||
@Param("startTime") Instant startTime,
|
||||
@Param("endTime") Instant endTime
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package xtools.app.sys.model.dto.req;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLogAccountReq</p>
|
||||
* <p>Description : 系统操作日志去重账号信息请求对象</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : xujun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026-07-25 10:00:00
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SysOptLogAccountReq implements Serializable {
|
||||
|
||||
/**
|
||||
* 账号ID
|
||||
*/
|
||||
@Schema(description = "账号ID")
|
||||
private Long accountId;
|
||||
|
||||
/**
|
||||
* 创建时间范围[开始时间(包含),结束时间(包含)],不能为空且需同时包含开始,结束时间
|
||||
*/
|
||||
@NotNull(message = "时间范围不能为空")
|
||||
@Schema(description = "创建时间范围(包含两端)", example = "['2026-07-17 00:00:00', '2026-07-24 23:59:59']")
|
||||
private Instant[] gmtCreateRange;
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package xtools.app.sys.model.dto.resp;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLogAccountResp</p>
|
||||
* <p>Description : 系统操作日志去重账号信息响应对象</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : xujun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026-07-25 10:00:00
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SysOptLogAccountResp implements Serializable {
|
||||
|
||||
/**
|
||||
* 账号ID
|
||||
*/
|
||||
@Schema(description = "账号ID")
|
||||
private Long accountId;
|
||||
|
||||
/**
|
||||
* 账号
|
||||
*/
|
||||
@Schema(description = "账号")
|
||||
private String account;
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package xtools.app.sys.model.dto.resp;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLogTitleCountResp</p>
|
||||
* <p>Description : 系统操作日志标题分组统计响应对象</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : xujun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026-07-25 10:00:00
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SysOptLogTitleCountResp implements Serializable {
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 操作次数
|
||||
*/
|
||||
@Schema(description = "操作次数")
|
||||
private Long count;
|
||||
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package xtools.app.sys.model.dto.resp;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Title : SysOptLogTitleTreeResp</p>
|
||||
* <p>Description : 系统操作日志标题统计树响应对象</p>
|
||||
* <p>Company : org.xujun</p>
|
||||
*
|
||||
* @author : xujun
|
||||
* @version : 1.0.0
|
||||
* @date : 2026-07-25 10:00:00
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SysOptLogTitleTreeResp implements Serializable {
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 操作次数
|
||||
*/
|
||||
@Schema(description = "操作次数")
|
||||
private Long count;
|
||||
|
||||
/**
|
||||
* 子节点
|
||||
*/
|
||||
@Schema(description = "子节点")
|
||||
private List<SysOptLogTitleTreeResp> children;
|
||||
|
||||
}
|
||||
+19
@@ -2,8 +2,11 @@ package xtools.app.sys.service;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import xtools.app.sys.model.dto.excel.SysOptLogExcel;
|
||||
import xtools.app.sys.model.dto.req.SysOptLogAccountReq;
|
||||
import xtools.app.sys.model.dto.req.SysOptLogPageReq;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogAccountResp;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogResp;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogTitleTreeResp;
|
||||
import xtools.boot.api.model.dto.Result;
|
||||
import xtools.boot.api.model.dto.page.PageReq;
|
||||
import xtools.boot.api.model.dto.page.PageResp;
|
||||
@@ -45,4 +48,20 @@ public interface SysOptLogService {
|
||||
*/
|
||||
List<SysOptLogExcel> exportExcel(SysOptLogPageReq req);
|
||||
|
||||
/**
|
||||
* 获取操作账号列表
|
||||
*
|
||||
* @param req 请求参数(时间范围)
|
||||
* @return 操作账号列表
|
||||
*/
|
||||
Result<List<SysOptLogAccountResp>> getAccountList(SysOptLogAccountReq req);
|
||||
|
||||
/**
|
||||
* 获取操作统计树
|
||||
*
|
||||
* @param req 请求参数(账号ID,时间范围)
|
||||
* @return 操作统计树
|
||||
*/
|
||||
Result<SysOptLogTitleTreeResp> getOptTree(SysOptLogAccountReq req);
|
||||
|
||||
}
|
||||
|
||||
+123
-1
@@ -11,11 +11,17 @@ import xtools.app.sys.auth.model.dto.OptLogDto;
|
||||
import xtools.app.sys.config.SysConfig;
|
||||
import xtools.app.sys.convert.SysOptLogConvert;
|
||||
import xtools.app.sys.model.dto.excel.SysOptLogExcel;
|
||||
import xtools.app.sys.model.dto.req.SysOptLogAccountReq;
|
||||
import xtools.app.sys.model.dto.req.SysOptLogPageReq;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogAccountResp;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogResp;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogTitleCountResp;
|
||||
import xtools.app.sys.model.dto.resp.SysOptLogTitleTreeResp;
|
||||
import xtools.app.sys.model.entity.SysOptLog;
|
||||
import xtools.app.sys.service.SysOptLogService;
|
||||
import xtools.app.sys.service.base.SysOptLogBaseService;
|
||||
import xtools.base.config.BaseParams;
|
||||
import xtools.boot.api.exection.BizWarning;
|
||||
import xtools.boot.api.model.dto.Result;
|
||||
import xtools.boot.api.model.dto.page.PageReq;
|
||||
import xtools.boot.api.model.dto.page.PageResp;
|
||||
@@ -25,6 +31,9 @@ import xtools.boot.ip.utils.IpUtils;
|
||||
import xtools.core.StringUtils;
|
||||
import xtools.extend.dto.IpAddrDto;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -44,7 +53,7 @@ import java.util.stream.Collectors;
|
||||
@Primary
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SysOptLogServiceImpl implements SysOptLogService {
|
||||
public class SysOptLogServiceImpl implements SysOptLogService, BaseParams {
|
||||
|
||||
private final SysConfig sysConfig;
|
||||
|
||||
@@ -193,4 +202,117 @@ public class SysOptLogServiceImpl implements SysOptLogService {
|
||||
QueryUtils.addTimeRange(query, req.getGmtCreateRange(), SysOptLog::getGmtCreate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取操作账号列表
|
||||
*
|
||||
* @param req 请求参数(时间范围)
|
||||
* @return 操作账号列表
|
||||
*/
|
||||
@Override
|
||||
public Result<List<SysOptLogAccountResp>> getAccountList(SysOptLogAccountReq req) {
|
||||
Instant[] range = req.getGmtCreateRange();
|
||||
if (Objects.isNull(range) || range.length != 2) {
|
||||
throw new BizWarning("时间范围不能为空且需要包含开始和结束时间");
|
||||
}
|
||||
Instant startTime = range[0];
|
||||
Instant endTime = range[1];
|
||||
if (startTime.isAfter(endTime)) {
|
||||
throw new BizWarning("开始时间不能大于结束时间");
|
||||
}
|
||||
// SQL 查询时间范围内去重账号信息
|
||||
List<SysOptLogAccountResp> list = sysOptLogBaseService.getBaseMapper().getOptAccountList(startTime, endTime);
|
||||
return Result.ok(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取操作统计树
|
||||
*
|
||||
* @param req 请求参数(账号ID,时间范围)
|
||||
* @return 操作统计树
|
||||
*/
|
||||
@Override
|
||||
public Result<SysOptLogTitleTreeResp> getOptTree(SysOptLogAccountReq req) {
|
||||
Instant[] range = req.getGmtCreateRange();
|
||||
if (Objects.isNull(range) || range.length != CP_NUM2) {
|
||||
throw new BizWarning("时间范围不能为空且需要包含开始和结束时间");
|
||||
}
|
||||
Instant startTime = range[CP_NUM0];
|
||||
Instant endTime = range[CP_NUM1];
|
||||
if (startTime.isAfter(endTime)) {
|
||||
throw new BizWarning("开始时间不能大于结束时间");
|
||||
}
|
||||
Long accountId = req.getAccountId();
|
||||
if (Objects.isNull(accountId)) {
|
||||
throw new BizWarning("账号ID不能为空");
|
||||
}
|
||||
// 获取该账号的操作日志
|
||||
List<SysOptLogTitleCountResp> list = sysOptLogBaseService.getBaseMapper().getOptCount(accountId, startTime, endTime);
|
||||
SysOptLogTitleTreeResp root = buildOptTree(list);
|
||||
root.setTitle(getAccount(accountId));
|
||||
return Result.ok(root);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询账号名称
|
||||
*
|
||||
* @param accountId 账号ID
|
||||
* @return 账号名称
|
||||
*/
|
||||
private String getAccount(Long accountId) {
|
||||
LambdaQueryWrapper<SysOptLog> query = new LambdaQueryWrapper<>();
|
||||
query.select(SysOptLog::getAccount);
|
||||
query.eq(SysOptLog::getAccountId, accountId);
|
||||
query.last("LIMIT 1");
|
||||
SysOptLog data = sysOptLogBaseService.getOne(query);
|
||||
return Objects.isNull(data) ? null : data.getAccount();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建操作统计树
|
||||
*
|
||||
* @param list 操作统计列表
|
||||
* @return 操作统计树
|
||||
*/
|
||||
private SysOptLogTitleTreeResp buildOptTree(List<SysOptLogTitleCountResp> list) {
|
||||
// 二层树节点Map
|
||||
Map<String, SysOptLogTitleTreeResp> groupMap = new HashMap<>(CP_NUM16);
|
||||
long total = 0L;
|
||||
for (SysOptLogTitleCountResp item : list) {
|
||||
String title = item.getTitle();
|
||||
Long count = item.getCount();
|
||||
// 获取模块名和方法名
|
||||
String module;
|
||||
String method;
|
||||
int idx = StringUtils.isBlank(title) ? CP_NEGATIVE1 : title.indexOf(CP_LINE);
|
||||
if (idx > CP_NUM0) {
|
||||
module = title.substring(CP_NUM0, idx);
|
||||
method = title.substring(idx + CP_NUM1);
|
||||
} else {
|
||||
module = title;
|
||||
method = title;
|
||||
}
|
||||
// 构建二层树节点
|
||||
SysOptLogTitleTreeResp parent = groupMap.computeIfAbsent(module, key -> SysOptLogTitleTreeResp.builder()
|
||||
.title(key)
|
||||
.count(0L)
|
||||
.children(new ArrayList<>())
|
||||
.build());
|
||||
// 构建三层树节点
|
||||
SysOptLogTitleTreeResp child = SysOptLogTitleTreeResp.builder()
|
||||
.title(method)
|
||||
.count(count)
|
||||
.build();
|
||||
parent.getChildren().add(child);
|
||||
// 累加二层树统计
|
||||
parent.setCount(parent.getCount() + count);
|
||||
// 累加根节点树统计
|
||||
total += count;
|
||||
}
|
||||
// 构造根节点
|
||||
return SysOptLogTitleTreeResp.builder()
|
||||
.count(total)
|
||||
.children(new ArrayList<>(groupMap.values()))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="xtools.app.sys.mapper.SysOptLogMapper">
|
||||
|
||||
<!-- 获取操作账号列表 -->
|
||||
<select id="getOptAccountList" resultType="xtools.app.sys.model.dto.resp.SysOptLogAccountResp">
|
||||
SELECT account_id AS accountId,
|
||||
MAX(account) AS account
|
||||
FROM sys_opt_log
|
||||
WHERE gmt_create BETWEEN #{startTime} AND #{endTime}
|
||||
GROUP BY account_id
|
||||
</select>
|
||||
|
||||
<!-- 获取该账号的操作日志 -->
|
||||
<select id="getOptCount" resultType="xtools.app.sys.model.dto.resp.SysOptLogTitleCountResp">
|
||||
SELECT title,
|
||||
COUNT(*) AS `count`
|
||||
FROM sys_opt_log
|
||||
WHERE account_id = #{accountId}
|
||||
AND gmt_create BETWEEN #{startTime} AND #{endTime}
|
||||
GROUP BY title
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user