fix: 加入api路径和样式修改

This commit is contained in:
2025-05-29 17:20:04 +08:00
parent df112f4e43
commit 5f052bb2b3
5 changed files with 146 additions and 15 deletions

View File

@@ -0,0 +1,23 @@
package org.nl.common.security.satoken;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Author: lyd
* @Date: 2025/5/29
*/
@Component
public class ApiPathInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 获取请求的API路径并存入MDC
String apiPath = request.getRequestURI();
MDC.put("apiPath", apiPath);
return true;
}
}

View File

@@ -26,6 +26,8 @@ public class SaTokenConfigure implements WebMvcConfigurer {
*/
@Autowired
private SecurityProperties securityProperties;
@Autowired
private ApiPathInterceptor apiPathInterceptor;
/**
* Sa-Token 整合 jwt (Simple 简单模式)
@@ -42,6 +44,10 @@ public class SaTokenConfigure implements WebMvcConfigurer {
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(apiPathInterceptor)
.addPathPatterns("/**")
// 设置最高优先级
.order(0);
/*
* 注册 Sa-Token 拦截器,打开注解式鉴权功能
* .excludePathPatterns(securityProperties.getExcludes()): 白名单

View File

@@ -30,7 +30,7 @@ public class SysNoticeController {
private ISysNoticeService noticeService;
@GetMapping
@Log("查询消息通知")
// @Log("查询消息通知")
public ResponseEntity<Object> query(@RequestParam Map whereJson, PageQuery page){
return new ResponseEntity<>(TableDataInfo.build(noticeService.queryAll(whereJson,page)),HttpStatus.OK);
}
@@ -56,13 +56,13 @@ public class SysNoticeController {
return new ResponseEntity<>(HttpStatus.OK);
}
@Log("获取未读的接收消息条数")
// @Log("获取未读的接收消息条数")
@GetMapping("/countByReceiveNotRead")
public ResponseEntity<Object> countByReceiveNotRead(){
return new ResponseEntity<>(noticeService.countByReceiveNotRead(), HttpStatus.OK);
}
@Log("接收消息分页")
// @Log("接收消息分页")
@GetMapping("/pageByReceive")
public ResponseEntity<Object> pageByReceive(){
return new ResponseEntity<>(noticeService.pageByReceive(), HttpStatus.OK);
@@ -75,7 +75,7 @@ public class SysNoticeController {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@Log("消息详情")
// @Log("消息详情")
@PostMapping("/findById")
public ResponseEntity<Object> findById(@RequestBody String id){
return new ResponseEntity<>(noticeService.getById(id), HttpStatus.OK);
@@ -90,7 +90,6 @@ public class SysNoticeController {
@Log("批量已读")
@PostMapping("/changeRead")
public ResponseEntity<Object> changeRead(@RequestBody JSONObject jsonObject) {
noticeService.changeRead(jsonObject);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);

View File

@@ -35,6 +35,9 @@ public class EsLogDto {
@Field(type = FieldType.Keyword)
private String thread;
@Field(type = FieldType.Keyword)
private String apiPath;
@Field(type = FieldType.Keyword)
private String logger;
@Field(type = FieldType.Keyword)
@@ -61,6 +64,14 @@ public class EsLogDto {
this.time = time;
}
public String getApiPath() {
return apiPath;
}
public void setApiPath(String apiPath) {
this.apiPath = apiPath;
}
public String getMessage() {
return message;
}

View File

@@ -81,12 +81,6 @@
<el-card shadow="hover" style="width: 100%" class="log-warpper">
<div style="width: 100%">
<div v-for="(log, index) in logs" :key="index">
<!-- <div v-if="compressedView === false" style="margin: 5px;font-size: 16px; word-break: break-all; white-space: pre-wrap;">-->
<!-- {{ timestampToDate(log.time) }} - {{log.severity}} - {{log.logger}} - [{{log.thread}}] - {{log.tlogTraceId}} - {{log.message}}-->
<!-- </div>-->
<!-- <div v-else style="margin-bottom: 5px; font-size: 16px;">-->
<!-- {{ timestampToDate(log.time) }} - {{log.severity}} - {{log.logger}} - [{{log.thread}}] - {{log.tlogTraceId}} - {{log.message}}-->
<!-- </div>-->
<div v-if="compressedView" style="margin-bottom: 5px; font-size: 16px;">
<span style="color: #000000;">{{ timestampToDate(log.time) }}</span> -
<span style="color: #000569;">{{ log.currIp === null ? '0.0.0.0' : log.currIp }}</span> -
@@ -94,9 +88,15 @@
<span style="color: #3498db;">{{ log.logger }}</span> -
<span style="color: #28b23a;">[{{ log.thread }}]</span> -
<span style="color: #d51313;">{{ log.tlogTraceId === null ? '无链路id' : log.tlogTraceId }}</span> -
<span style="color: #000000;">{{ log.message }}</span>
<span
style="color: #000000;"
class="sql-message"
@click="handleCopySQL(log.message)"
>
{{ log.message }}
</span>
</div>
<div v-else style="margin-bottom: 5px; font-size: 16px; border: #00afff 1px solid; padding: 5px;">
<div v-else style="margin-bottom: 5px; font-size: 16px; border: #999999 1px solid; padding: 5px;">
<el-row>
<el-col :span="2">
时间
@@ -105,6 +105,14 @@
<span style="color: #000000;">{{ timestampToDate(log.time) }}</span>
</el-col>
</el-row>
<el-row>
<el-col :span="2">
host
</el-col>
<el-col :span="22">
<span style="color: #048815;">{{ log.host }}</span>
</el-col>
</el-row>
<el-row>
<el-col :span="2">
执行IP
@@ -113,6 +121,22 @@
<span style="color: #000569;">{{ log.currIp === null ? '0.0.0.0' : log.currIp }}</span>
</el-col>
</el-row>
<el-row>
<el-col :span="2">
API路径
</el-col>
<el-col :span="22">
<span style="color: #b9de16;">{{ log.apiPath === null ? '无' : log.apiPath }}</span>
</el-col>
</el-row>
<el-row>
<el-col :span="2">
MDC标签
</el-col>
<el-col :span="22">
<span style="color: #d20118;">{{ log.tag === null ? '未配置MDC' : log.tag }}</span>
</el-col>
</el-row>
<el-row>
<el-col :span="2">
日志级别
@@ -150,7 +174,13 @@
日志信息
</el-col>
<el-col :span="22">
<span style="color: #000000;">{{ log.message }}</span>
<span
style="color: #000000;"
class="sql-message"
@click="handleCopySQL(log.message)"
>
{{ log.message }}
</span>
</el-col>
</el-row>
</div>
@@ -228,6 +258,60 @@ export default {
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliseconds}`
},
// 处理SQL复制
handleCopySQL(message) {
// 1. 使用正则匹配SQL语句
const sqlMatch = message.match(/\[ SQL: ([^\]]+)\s*\]/)
if (sqlMatch && sqlMatch[1]) {
const sql = sqlMatch[1].trim()
this.copyToClipboard(sql)
} else {
this.$message.warning('未检测到可复制的SQL语句')
}
},
// 复制文本到剪贴板
copyToClipboard(text) {
// 现代浏览器方法
if (navigator.clipboard) {
navigator.clipboard.writeText(text)
.then(() => this.showSuccess())
.catch(err => this.showError(err))
}
// 兼容旧浏览器
else {
const textarea = document.createElement('textarea')
textarea.value = text
textarea.style.position = 'fixed'
document.body.appendChild(textarea)
textarea.select()
try {
const success = document.execCommand('copy')
success ? this.showSuccess() : this.showError()
} catch (err) {
this.showError(err)
}
document.body.removeChild(textarea)
}
},
// 显示成功提示
showSuccess() {
this.$message({
message: 'SQL已复制到剪贴板',
type: 'success',
duration: 2000
})
},
// 显示错误提示
showError(err) {
console.error('复制失败:', err)
this.$message.error('复制失败,请手动复制')
},
handleSizeChange(val) {
this.query.size = val
this.queryData()
@@ -257,5 +341,13 @@ export default {
</script>
<style scoped>
/* 可点击样式提示 */
.sql-message {
cursor: pointer;
transition: all 0.3s;
}
.sql-message:hover {
background-color: #f0f9ff;
box-shadow: 0 0 3px rgba(32, 160, 255, 0.5);
}
</style>