系统日志

This commit is contained in:
2026-01-01 17:01:56 +08:00
parent b53faca120
commit 05c76fa3ec
22 changed files with 757 additions and 418 deletions

View File

@@ -1,6 +1,5 @@
CREATE SCHEMA IF NOT EXISTS log;
DROP TABLE IF EXISTS log.tb_sys_log CASCADE;
CREATE TABLE log.tb_sys_log (
DROP TABLE IF EXISTS sys.tb_sys_log CASCADE;
CREATE TABLE sys.tb_sys_log (
optsn VARCHAR(50) NOT NULL, -- 流水号
log_id VARCHAR(50) NOT NULL, -- 日志ID
type VARCHAR(50) NOT NULL, -- 日志类型
@@ -13,7 +12,8 @@ CREATE TABLE log.tb_sys_log (
message VARCHAR(255) NOT NULL, -- 日志消息
data JSONB DEFAULT NULL, -- 日志数据
creator VARCHAR(50) DEFAULT NULL, -- 创建者
service_type VARCHAR(50) NOT NULL, -- 服务类型
creator_name VARCHAR(200) DEFAULT NULL, -- 创建者姓名
service VARCHAR(50) NOT NULL, -- 服务类型
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
updater VARCHAR(50) DEFAULT NULL, -- 更新者
create_time TIMESTAMPTZ NOT NULL DEFAULT now(), -- 日志创建时间
@@ -23,19 +23,20 @@ CREATE TABLE log.tb_sys_log (
PRIMARY KEY (log_id),
UNIQUE (optsn)
);
COMMENT ON TABLE log.tb_sys_log IS '系统日志表';
COMMENT ON COLUMN log.tb_sys_log.optsn IS '流水号';
COMMENT ON COLUMN log.tb_sys_log.log_id IS '日志ID';
COMMENT ON COLUMN log.tb_sys_log.type IS '日志类型';
COMMENT ON COLUMN log.tb_sys_log.level IS '日志级别';
COMMENT ON COLUMN log.tb_sys_log.module IS '日志模块';
COMMENT ON COLUMN log.tb_sys_log.message IS '日志消息';
COMMENT ON COLUMN log.tb_sys_log.data IS '日志数据';
COMMENT ON COLUMN log.tb_sys_log.creator IS '创建者';
COMMENT ON COLUMN log.tb_sys_log.service_type IS '服务类型';
COMMENT ON COLUMN log.tb_sys_log.dept_path IS '部门全路径';
COMMENT ON COLUMN log.tb_sys_log.updater IS '更新者';
COMMENT ON COLUMN log.tb_sys_log.create_time IS '日志创建时间';
COMMENT ON COLUMN log.tb_sys_log.update_time IS '日志更新时间';
COMMENT ON COLUMN log.tb_sys_log.delete_time IS '日志删除时间';
COMMENT ON COLUMN log.tb_sys_log.deleted IS '是否删除';
COMMENT ON TABLE sys.tb_sys_log IS '系统日志表';
COMMENT ON COLUMN sys.tb_sys_log.optsn IS '流水号';
COMMENT ON COLUMN sys.tb_sys_log.log_id IS '日志ID';
COMMENT ON COLUMN sys.tb_sys_log.type IS '日志类型';
COMMENT ON COLUMN sys.tb_sys_log.level IS '日志级别';
COMMENT ON COLUMN sys.tb_sys_log.module IS '日志模块';
COMMENT ON COLUMN sys.tb_sys_log.message IS '日志消息';
COMMENT ON COLUMN sys.tb_sys_log.data IS '日志数据';
COMMENT ON COLUMN sys.tb_sys_log.creator IS '创建者';
COMMENT ON COLUMN sys.tb_sys_log.creator_name IS '创建者姓名';
COMMENT ON COLUMN sys.tb_sys_log.service IS '服务类型';
COMMENT ON COLUMN sys.tb_sys_log.dept_path IS '部门全路径';
COMMENT ON COLUMN sys.tb_sys_log.updater IS '更新者';
COMMENT ON COLUMN sys.tb_sys_log.create_time IS '日志创建时间';
COMMENT ON COLUMN sys.tb_sys_log.update_time IS '日志更新时间';
COMMENT ON COLUMN sys.tb_sys_log.delete_time IS '日志删除时间';
COMMENT ON COLUMN sys.tb_sys_log.deleted IS '是否删除';

View File

@@ -8,7 +8,7 @@ CREATE TABLE message.tb_message (
content VARCHAR(255) NOT NULL, -- 消息内容
type VARCHAR(50) NOT NULL, -- 消息类型
status VARCHAR(50) NOT NULL, -- 消息状态
service_type VARCHAR(50) NOT NULL, -- 服务类型
service VARCHAR(50) NOT NULL, -- 服务类型
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径(隔离)
creator VARCHAR(50) NOT NULL DEFAULT 'system',-- 创建者
updater VARCHAR(50) DEFAULT NULL, -- 更新者
@@ -27,7 +27,7 @@ COMMENT ON COLUMN message.tb_message.title IS '消息标题';
COMMENT ON COLUMN message.tb_message.content IS '消息内容';
COMMENT ON COLUMN message.tb_message.type IS '消息类型';
COMMENT ON COLUMN message.tb_message.status IS '消息状态';
COMMENT ON COLUMN message.tb_message.service_type IS '服务类型';
COMMENT ON COLUMN message.tb_message.service IS '服务类型';
COMMENT ON COLUMN message.tb_message.dept_path IS '部门全路径';
COMMENT ON COLUMN message.tb_message.creator IS '创建者';
COMMENT ON COLUMN message.tb_message.updater IS '更新者';
@@ -166,7 +166,7 @@ CREATE TABLE message.tb_message_template (
title_template TEXT, -- 标题模板(支持变量)
content_template TEXT NOT NULL, -- 内容模板(支持变量)
variables JSONB, -- 模板变量定义
service_type VARCHAR(50) NOT NULL, -- 服务类型
service VARCHAR(50) NOT NULL, -- 服务类型
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
creator VARCHAR(50) DEFAULT NULL, -- 创建者
updater VARCHAR(50) DEFAULT NULL, -- 更新者
@@ -188,7 +188,7 @@ COMMENT ON COLUMN message.tb_message_template.template_type IS '模板类型s
COMMENT ON COLUMN message.tb_message_template.title_template IS '标题模板(支持变量)';
COMMENT ON COLUMN message.tb_message_template.content_template IS '内容模板(支持变量)';
COMMENT ON COLUMN message.tb_message_template.variables IS '模板变量定义';
COMMENT ON COLUMN message.tb_message_template.service_type IS '服务类型';
COMMENT ON COLUMN message.tb_message_template.service IS '服务类型';
COMMENT ON COLUMN message.tb_message_template.dept_path IS '部门全路径';
COMMENT ON COLUMN message.tb_message_template.creator IS '创建者';
COMMENT ON COLUMN message.tb_message_template.updater IS '更新者';

View File

@@ -74,7 +74,7 @@ INSERT INTO message.tb_message_channel (
-- =============================
INSERT INTO message.tb_message_template (
optsn, template_id, template_code, template_name, template_type,
title_template, content_template, variables, service_type,
title_template, content_template, variables, service,
creator, create_time, deleted
) VALUES
-- 用户注册欢迎消息

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xyzh</groupId>
<artifactId>apis</artifactId>
<version>1.0.0</version>
</parent>
<groupId>org.xyzh.apis</groupId>
<artifactId>api-log</artifactId>
<version>${urban-lifeline.version}</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
</project>

View File

@@ -59,5 +59,5 @@ public class MessageReceiverVO extends BaseVO {
private Date handleTime;
@Schema(description = "服务类型")
private String serviceType;
private String service;
}

View File

@@ -0,0 +1,18 @@
package org.xyzh.api.system.constance;
public class SysLogContants {
private final static String LOG_LEVEL_DEBUG = "DEBUG";
private final static String LOG_LEVEL_INFO = "INFO";
private final static String LOG_LEVEL_WARN = "WARN";
private final static String LOG_LEVEL_ERROR = "ERROR";
private final static String LOG_MODULE_SYSTEM = "系统";
private final static String LOG_MODULE_AI = "AI服务";
private final static String LOG_MODULE_AUTH = "日志";
private final static String LOG_MODULE_WORKCASE = "工单";
private final static String LOG_MODULE_KNOWLEDGE = "知识库";
private final static String LOG_MODULE_FILE = "文件";
}

View File

@@ -1,4 +1,4 @@
package org.xyzh.api.log.dto;
package org.xyzh.api.system.dto;
import com.alibaba.fastjson2.JSONObject;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -48,4 +48,10 @@ public class TbSysLogDTO extends BaseDTO {
@Schema(description = "日志数据")
private JSONObject data;
@Schema(description = "创建人姓名")
private String creatorName;
@Schema(description = "服务")
private String servce;
}

View File

@@ -1,4 +1,4 @@
package org.xyzh.api.log.dto;
package org.xyzh.api.system.dto;
import java.util.Date;
import com.alibaba.fastjson2.annotation.JSONField;

View File

@@ -0,0 +1,54 @@
package org.xyzh.api.system.service;
import java.util.List;
import org.xyzh.api.system.dto.TbSysLogDTO;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageRequest;
/**
* @description 系统日志服务
* @filename LogService.java
* @author yslg
* @copyright yslg
* @since 2026-01-01
*/
public interface LogService {
/**
* @description 统计系统日志
* @param sysLog
* @return 返回值描述
* @author yslg
* @since 2026-01-01
*/
ResultDomain<TbSysLogDTO> addSysLog(TbSysLogDTO sysLog);
/**
* @description 统计日志数量
* @param filter
* @return 返回值描述
* @author yslg
* @since 2026-01-01
*/
ResultDomain<Integer> countSysLog(TbSysLogDTO filter);
/**
* @description 获取日志列表
* @param filter
* @return 日志列表
* @author yslg
* @since 2026-01-01
*/
ResultDomain<TbSysLogDTO> getSysLogList(TbSysLogDTO filter);
/**
* @description 获取日志分页
* @param pageRequest
* @return 日志分页
* @author yslg
* @since 2026-01-01
*/
ResultDomain<TbSysLogDTO> getSysLogPage(PageRequest<TbSysLogDTO> pageRequest);
}

View File

@@ -18,7 +18,6 @@
<module>api-auth</module>
<module>api-file</module>
<module>api-message</module>
<module>api-log</module>
<module>api-system</module>
<module>api-crontab</module>
<module>api-ai</module>
@@ -59,11 +58,6 @@
<artifactId>api-system</artifactId>
<version>${urban-lifeline.version}</version>
</dependency>
<dependency>
<groupId>org.xyzh.apis</groupId>
<artifactId>api-log</artifactId>
<version>${urban-lifeline.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@@ -1,111 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xyzh</groupId>
<artifactId>urban-lifeline</artifactId>
<version>1.0.0</version>
</parent>
<groupId>org.xyzh</groupId>
<artifactId>log</artifactId>
<version>${urban-lifeline.version}</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.xyzh.apis</groupId>
<artifactId>api-log</artifactId>
<version>${urban-lifeline.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Log4j2 日志 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- Dubbo Spring Boot Starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<!-- Dubbo Nacos Spring Boot Starter (服务注册与发现) -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-nacos-spring-boot-starter</artifactId>
</dependency>
<!-- Spring Cloud Alibaba Nacos Discovery (可选,用于服务发现) -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-logback-adapter-12</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>logback-adapter</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<!-- MyBatis-Plus (可选,如不需要增强 CRUD 可移除) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.plus.version}</version>
<exclusions>
<!-- 排除旧版 mybatis-spring防止与 3.x 冲突 -->
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 强制引入与 Spring Boot 3.x 匹配的 mybatis-spring 3.x -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis.spring.version}</version>
</dependency>
<!-- SpringDoc OpenAPI -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,24 +0,0 @@
package org.xyzh.log;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@EnableDubbo // 启用 Dubbo 服务
@ComponentScan(basePackages = {
"org.xyzh.log", // log 模块
"org.xyzh.common" // 公共模块
})
public class LogApp {
private static final Logger logger = LoggerFactory.getLogger(LogApp.class);
public static void main(String[] args) {
logger.info("======================== LogApp 启动中 =========================");
SpringApplication.run(LogApp.class, args);
logger.info("======================== LogApp 启动成功 =========================");
}
}

View File

@@ -1,58 +0,0 @@
package org.xyzh.log.config;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
/**
* OpenAPI 配置类 - Log 服务
* 配置 Swagger/OpenAPI 文档,方便 Apifox 导入接口和对象进行测试
*
* @author yslg
*/
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI logOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("日志服务 API 文档")
.description("""
日志服务接口文档,包括系统日志、登录日志等功能。
## 使用说明
1. 访问 Swagger UI: http://localhost:8083/urban-lifeline/log/swagger-ui.html
2. 访问 OpenAPI JSON: http://localhost:8083/urban-lifeline/log/v3/api-docs
3. 在 Apifox 中导入 OpenAPI JSON 进行接口测试
""")
.version("1.0.0")
.contact(new Contact()
.name("yslg")
.email("3401275564@qq.com"))
.license(new License()
.name("Apache 2.0")
.url("https://www.apache.org/licenses/LICENSE-2.0.html")))
.servers(List.of(
new Server().url("http://localhost:8083/urban-lifeline/log").description("本地开发环境")
))
.addSecurityItem(new SecurityRequirement().addList("Bearer Authentication"))
.components(new Components()
.addSecuritySchemes("Bearer Authentication",
new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
.description("请输入JWT Token格式Bearer {token}")));
}
}

View File

@@ -1,99 +0,0 @@
# ================== Server ==================
server:
port: 8183
# servlet:
# context-path: /urban-lifeline/log # 微服务架构下context-path由Gateway管理
# ================== Auth ====================
auth:
enabled: true
gateway-mode: true
whitelist:
- /swagger-ui/**
- /swagger-ui.html
- /v3/api-docs/**
- /webjars/**
- /favicon.ico
- /error
- /actuator/health
- /actuator/info
security:
aes:
secret-key: 1234567890qwer
# ================== Spring ==================
spring:
application:
name: log-service
# ================== Spring Cloud Nacos ==================
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev
group: DEFAULT_GROUP
# ================== DataSource ==================
datasource:
url: jdbc:postgresql://127.0.0.1:5432/urban_lifeline
username: postgres
password: postgres
driver-class-name: org.postgresql.Driver
# ================== Redis ==================
data:
redis:
host: 127.0.0.1 # 如果是 docker 跑的 redis按实际 host / 端口改
port: 6379
database: 0
password: 123456 # 如果有密码就填上,没密码可以去掉这一行
# ================== SpringDoc ==================
springdoc:
api-docs:
enabled: true
path: /v3/api-docs
swagger-ui:
enabled: true
path: /swagger-ui.html
try-it-out-enabled: true
show-common-extensions: true
show-extensions: true
show-request-duration: true
filter: true
tags-sorter: alpha
operations-sorter: alpha
group-configs:
- group: 'default'
display-name: '日志服务 API'
paths-to-match: '/**'
# ================== Dubbo + Nacos ==================
dubbo:
application:
name: urban-lifeline-log
qos-enable: false
protocol:
name: dubbo
port: -1
registry:
address: nacos://127.0.0.1:8848
scan:
base-packages: org.xyzh.log.service.impl
# ================== MyBatis ==================
mybatis-plus:
mapper-locations: classpath:mapper/**/*.xml
type-aliases-package: org.xyzh.common.dto, org.xyzh.api
# ================== Logging ==================
logging:
config: classpath:log4j2.xml
charset:
console: UTF-8
file: UTF-8
level:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping: TRACE

View File

@@ -1,65 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="WARN" monitorInterval="30">
<Properties>
<property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
<property name="FILE_PATH" value="./logs" />
<property name="FILE_NAME" value="log-service" />
<property name="file.encoding" value="UTF-8" />
<property name="console.encoding" value="UTF-8" />
</Properties>
<appenders>
<console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
<ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/>
</console>
<RollingFile name="RollingFile" fileName="${FILE_PATH}/${FILE_NAME}.log"
filePattern="${FILE_PATH}/${FILE_NAME}-%d{yyyy-MM-dd}_%i.log.gz">
<ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<DefaultRolloverStrategy max="30"/>
</RollingFile>
</appenders>
<loggers>
<logger name="com.alibaba.nacos" level="info" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</logger>
<logger name="org.mybatis" level="debug" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</logger>
<Logger name="org.springframework" level="info" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Logger>
<Logger name="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" level="TRACE" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Logger>
<Logger name="org.xyzh.log" level="debug" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Logger>
<Logger name="org.xyzh.common" level="debug" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Logger>
<root level="info">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFile"/>
</root>
</loggers>
</configuration>

View File

@@ -11,7 +11,6 @@
<module>common</module>
<module>apis</module>
<module>gateway</module>
<module>log</module>
<module>system</module>
<module>auth</module>
<module>file</module>

View File

@@ -0,0 +1,69 @@
package org.xyzh.system.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.xyzh.api.system.dto.TbSysLogDTO;
import org.xyzh.api.system.service.LogService;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageRequest;
/**
* @description 系统日志控制器
* @filename LogController.java
* @author yslg
* @copyright yslg
* @since 2026-01-01
*/
@RestController
@RequestMapping("/system/log")
public class LogController {
private static final Logger logger = LoggerFactory.getLogger(LogController.class);
@Autowired
private LogService logService;
// ================= 系统日志相关接口 =================
/**
* 添加系统日志
*/
@PostMapping
@PreAuthorize("hasAuthority('log:log:add')")
public ResultDomain<TbSysLogDTO> addSysLog(@RequestBody TbSysLogDTO sysLog) {
return logService.addSysLog(sysLog);
}
/**
* 统计日志数量
*/
@PostMapping("/count")
@PreAuthorize("hasAuthority('log:log:view')")
public ResultDomain<Integer> countSysLog(@RequestBody TbSysLogDTO filter) {
return logService.countSysLog(filter);
}
/**
* 获取日志列表
*/
@PostMapping("/list")
@PreAuthorize("hasAuthority('log:log:view')")
public ResultDomain<TbSysLogDTO> getSysLogList(@RequestBody TbSysLogDTO filter) {
return logService.getSysLogList(filter);
}
/**
* 分页查询日志
*/
@PostMapping("/page")
@PreAuthorize("hasAuthority('log:log:view')")
public ResultDomain<TbSysLogDTO> getSysLogPage(@RequestBody PageRequest<TbSysLogDTO> pageRequest) {
return logService.getSysLogPage(pageRequest);
}
}

View File

@@ -1,11 +1,11 @@
package org.xyzh.log.mapper.log;
package org.xyzh.system.mapper.log;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.xyzh.api.system.dto.TbSysLogDTO;
import org.xyzh.common.core.page.PageParam;
import org.xyzh.api.log.dto.TbSysLogDTO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

View File

@@ -1,11 +1,11 @@
package org.xyzh.log.mapper.log;
package org.xyzh.system.mapper.log;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.xyzh.api.system.dto.TbSysLoginLogDTO;
import org.xyzh.common.core.page.PageParam;
import org.xyzh.api.log.dto.TbSysLoginLogDTO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

View File

@@ -0,0 +1,137 @@
package org.xyzh.system.service.impl;
import jakarta.annotation.Resource;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xyzh.api.system.dto.TbSysLogDTO;
import org.xyzh.api.system.service.LogService;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageDomain;
import org.xyzh.common.core.page.PageParam;
import org.xyzh.common.core.page.PageRequest;
import org.xyzh.common.utils.StringUtils;
import org.xyzh.common.utils.id.IdUtil;
import org.xyzh.system.mapper.log.TbSysLogMapper;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/**
* @description 系统日志服务实现类
* @filename LogServiceImpl.java
* @author yslg
* @copyright yslg
* @since 2026-01-01
*/
@DubboService(
version = "1.0.0",
group = "system",
timeout = 3000,
retries = 0
)
public class LogServiceImpl implements LogService {
private static final Logger logger = LoggerFactory.getLogger(LogServiceImpl.class);
private static final String MSG_LOG_PARAM_REQUIRED = "日志参数不能为空";
private static final String MSG_FILTER_PARAM_REQUIRED = "查询条件不能为空";
private static final String MSG_PAGE_PARAM_REQUIRED = "分页参数不能为空";
@Resource
private TbSysLogMapper sysLogMapper;
@Override
public ResultDomain<TbSysLogDTO> addSysLog(TbSysLogDTO sysLog) {
if (sysLog == null) {
return ResultDomain.failure(MSG_LOG_PARAM_REQUIRED);
}
try {
// 设置默认值
if (StringUtils.isBlank(sysLog.getLogId())) {
sysLog.setLogId(IdUtil.generateID());
}
if (StringUtils.isBlank(sysLog.getOptsn())) {
sysLog.setOptsn(IdUtil.generateID());
}
if (sysLog.getCreateTime() == null) {
sysLog.setCreateTime(new Date());
}
if (sysLog.getDeleted() == null) {
sysLog.setDeleted(false);
}
int rows = sysLogMapper.insertLog(sysLog);
if (rows > 0) {
logger.info("添加系统日志成功, logId={}", sysLog.getLogId());
return ResultDomain.success("添加系统日志成功", sysLog);
}
logger.warn("添加系统日志失败, logId={}", sysLog.getLogId());
return ResultDomain.failure("添加系统日志失败");
} catch (Exception e) {
logger.error("添加系统日志异常", e);
return ResultDomain.failure("添加系统日志异常: " + e.getMessage());
}
}
@Override
public ResultDomain<Integer> countSysLog(TbSysLogDTO filter) {
if (filter == null) {
return ResultDomain.failure(MSG_FILTER_PARAM_REQUIRED);
}
try {
int count = sysLogMapper.getLogCount(filter);
return ResultDomain.success("统计日志数量成功", count);
} catch (Exception e) {
logger.error("统计日志数量异常", e);
return ResultDomain.failure("统计日志数量异常: " + e.getMessage());
}
}
@Override
public ResultDomain<TbSysLogDTO> getSysLogList(TbSysLogDTO filter) {
try {
List<TbSysLogDTO> list = sysLogMapper.getLogByFilter(filter);
if (list == null) {
list = Collections.emptyList();
}
return ResultDomain.success("获取日志列表成功", list);
} catch (Exception e) {
logger.error("获取日志列表异常", e);
return ResultDomain.failure("获取日志列表异常: " + e.getMessage());
}
}
@Override
public ResultDomain<TbSysLogDTO> getSysLogPage(PageRequest<TbSysLogDTO> pageRequest) {
if (pageRequest == null) {
return ResultDomain.failure(MSG_PAGE_PARAM_REQUIRED);
}
try {
PageParam pageParam = pageRequest.getPageParam();
TbSysLogDTO filter = pageRequest.getFilter();
// 查询总数
int total = sysLogMapper.getLogCount(filter);
pageParam.setTotal(total);
pageParam.setTotalPages(pageParam.getPageSize() == 0 ? 0 :
(int) Math.ceil((double) total / pageParam.getPageSize()));
// 查询分页数据
List<TbSysLogDTO> data = sysLogMapper.getLogPageByFilter(filter, pageParam);
if (data == null) {
data = Collections.emptyList();
}
PageDomain<TbSysLogDTO> pageDomain = new PageDomain<>(pageParam, data);
return ResultDomain.success("分页查询日志成功", pageDomain);
} catch (Exception e) {
logger.error("分页查询日志异常", e);
return ResultDomain.failure("分页查询日志异常: " + e.getMessage());
}
}
}

View File

@@ -0,0 +1,254 @@
<?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="org.xyzh.system.mapper.log.TbSysLogMapper">
<!-- 结果映射 -->
<resultMap id="BaseResultMap" type="org.xyzh.api.system.dto.TbSysLogDTO">
<id column="log_id" property="logId" jdbcType="VARCHAR"/>
<result column="optsn" property="optsn" jdbcType="VARCHAR"/>
<result column="type" property="type" jdbcType="INTEGER"/>
<result column="level" property="level" jdbcType="VARCHAR"/>
<result column="module" property="module" jdbcType="VARCHAR"/>
<result column="ip_address" property="ipAddress" jdbcType="VARCHAR"/>
<result column="ip_source" property="ip_source" jdbcType="VARCHAR"/>
<result column="browser" property="browser" jdbcType="VARCHAR"/>
<result column="os" property="os" jdbcType="VARCHAR"/>
<result column="message" property="message" jdbcType="VARCHAR"/>
<result column="data" property="data" typeHandler="org.xyzh.common.jdbc.handler.FastJson2TypeHandler"/>
<result column="creator" property="creator" jdbcType="VARCHAR"/>
<result column="creator_name" property="creatorName" jdbcType="VARCHAR"/>
<result column="service" property="servce" jdbcType="VARCHAR"/>
<result column="dept_path" property="deptPath" jdbcType="VARCHAR"/>
<result column="updater" property="updater" jdbcType="VARCHAR"/>
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
<result column="delete_time" property="deleteTime" jdbcType="TIMESTAMP"/>
<result column="deleted" property="deleted" jdbcType="BOOLEAN"/>
</resultMap>
<!-- 基础列 -->
<sql id="Base_Column_List">
log_id, optsn, type, level, module, ip_address, ip_source, browser, os, message,
data, creator, creator_name, service, dept_path, updater,
create_time, update_time, delete_time, deleted
</sql>
<!-- 插入系统日志 -->
<insert id="insertLog" parameterType="org.xyzh.api.system.dto.TbSysLogDTO">
INSERT INTO sys.tb_sys_log
<trim prefix="(" suffix=")" suffixOverrides=",">
log_id,
optsn,
type,
level,
module,
message,
service,
<if test="ipAddress != null and ipAddress != ''">ip_address,</if>
<if test="ip_source != null and ip_source != ''">ip_source,</if>
<if test="browser != null and browser != ''">browser,</if>
<if test="os != null and os != ''">os,</if>
<if test="data != null">data,</if>
<if test="creator != null and creator != ''">creator,</if>
<if test="creatorName != null and creatorName != ''">creator_name,</if>
<if test="deptPath != null and deptPath != ''">dept_path,</if>
<if test="updater != null and updater != ''">updater,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
<if test="deleteTime != null">delete_time,</if>
<if test="deleted != null">deleted,</if>
</trim>
VALUES
<trim prefix="(" suffix=")" suffixOverrides=",">
#{logId},
#{optsn},
#{type},
#{level},
#{module},
#{message},
#{servce},
<if test="ipAddress != null and ipAddress != ''">#{ipAddress},</if>
<if test="ip_source != null and ip_source != ''">#{ip_source},</if>
<if test="browser != null and browser != ''">#{browser},</if>
<if test="os != null and os != ''">#{os},</if>
<if test="data != null">#{data, typeHandler=org.xyzh.common.jdbc.handler.FastJson2TypeHandler},</if>
<if test="creator != null and creator != ''">#{creator},</if>
<if test="creatorName != null and creatorName != ''">#{creatorName},</if>
<if test="deptPath != null and deptPath != ''">#{deptPath},</if>
<if test="updater != null and updater != ''">#{updater},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="deleteTime != null">#{deleteTime},</if>
<if test="deleted != null">#{deleted},</if>
</trim>
</insert>
<!-- 更新系统日志 -->
<update id="updateLog" parameterType="org.xyzh.api.system.dto.TbSysLogDTO">
UPDATE sys.tb_sys_log
<set>
<if test="type != null">type = #{type},</if>
<if test="level != null and level != ''">level = #{level},</if>
<if test="module != null and module != ''">module = #{module},</if>
<if test="ipAddress != null and ipAddress != ''">ip_address = #{ipAddress},</if>
<if test="ip_source != null and ip_source != ''">ip_source = #{ip_source},</if>
<if test="browser != null and browser != ''">browser = #{browser},</if>
<if test="os != null and os != ''">os = #{os},</if>
<if test="message != null and message != ''">message = #{message},</if>
<if test="data != null">data = #{data, typeHandler=org.xyzh.common.jdbc.handler.FastJson2TypeHandler},</if>
<if test="servce != null and servce != ''">service = #{servce},</if>
<if test="updater != null and updater != ''">updater = #{updater},</if>
<if test="deptPath != null and deptPath != ''">dept_path = #{deptPath},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="deleteTime != null">delete_time = #{deleteTime},</if>
<if test="deleted != null">deleted = #{deleted},</if>
</set>
WHERE log_id = #{logId}
</update>
<!-- 删除系统日志 -->
<update id="deleteLog" parameterType="org.xyzh.api.system.dto.TbSysLogDTO">
UPDATE sys.tb_sys_log
SET deleted = true,
delete_time = NOW()
WHERE log_id = #{logId}
</update>
<!-- 根据日志ID查询系统日志 -->
<select id="getLogById" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List" />
FROM sys.tb_sys_log
WHERE log_id = #{logId}
AND (deleted IS NULL OR deleted = false)
</select>
<!-- 根据条件查询系统日志列表 -->
<select id="getLogByFilter" resultMap="BaseResultMap" parameterType="org.xyzh.api.system.dto.TbSysLogDTO">
SELECT <include refid="Base_Column_List" />
FROM sys.tb_sys_log
<where>
<if test="filter.logId != null and filter.logId != ''">
AND log_id = #{filter.logId}
</if>
<if test="filter.type != null">
AND type = #{filter.type}
</if>
<if test="filter.level != null and filter.level != ''">
AND level = #{filter.level}
</if>
<if test="filter.module != null and filter.module != ''">
AND module = #{filter.module}
</if>
<if test="filter.ipAddress != null and filter.ipAddress != ''">
AND ip_address = #{filter.ipAddress}
</if>
<if test="filter.creator != null and filter.creator != ''">
AND creator = #{filter.creator}
</if>
<if test="filter.servce != null and filter.servce != ''">
AND service = #{filter.servce}
</if>
<if test="filter.deptPath != null and filter.deptPath != ''">
AND dept_path LIKE CONCAT(#{filter.deptPath}, '%')
</if>
<if test="filter.message != null and filter.message != ''">
AND message LIKE CONCAT('%', #{filter.message}, '%')
</if>
<if test="filter.startTime != null">
AND create_time &gt;= #{filter.startTime}
</if>
<if test="filter.endTime != null">
AND create_time &lt;= #{filter.endTime}
</if>
AND (deleted IS NULL OR deleted = false)
</where>
ORDER BY create_time DESC
</select>
<!-- 根据条件查询系统日志分页列表 -->
<select id="getLogPageByFilter" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List" />
FROM sys.tb_sys_log
<where>
<if test="filter.logId != null and filter.logId != ''">
AND log_id = #{filter.logId}
</if>
<if test="filter.type != null">
AND type = #{filter.type}
</if>
<if test="filter.level != null and filter.level != ''">
AND level = #{filter.level}
</if>
<if test="filter.module != null and filter.module != ''">
AND module = #{filter.module}
</if>
<if test="filter.ipAddress != null and filter.ipAddress != ''">
AND ip_address = #{filter.ipAddress}
</if>
<if test="filter.creator != null and filter.creator != ''">
AND creator = #{filter.creator}
</if>
<if test="filter.servce != null and filter.servce != ''">
AND service = #{filter.servce}
</if>
<if test="filter.deptPath != null and filter.deptPath != ''">
AND dept_path LIKE CONCAT(#{filter.deptPath}, '%')
</if>
<if test="filter.message != null and filter.message != ''">
AND message LIKE CONCAT('%', #{filter.message}, '%')
</if>
<if test="filter.startTime != null">
AND create_time &gt;= #{filter.startTime}
</if>
<if test="filter.endTime != null">
AND create_time &lt;= #{filter.endTime}
</if>
AND (deleted IS NULL OR deleted = false)
</where>
ORDER BY create_time DESC
LIMIT #{pageParam.pageSize} OFFSET #{pageParam.offset}
</select>
<!-- 根据条件查询系统日志数量 -->
<select id="getLogCount" resultType="java.lang.Integer" parameterType="org.xyzh.api.system.dto.TbSysLogDTO">
SELECT COUNT(1)
FROM sys.tb_sys_log
<where>
<if test="logId != null and logId != ''">
AND log_id = #{logId}
</if>
<if test="type != null">
AND type = #{type}
</if>
<if test="level != null and level != ''">
AND level = #{level}
</if>
<if test="module != null and module != ''">
AND module = #{module}
</if>
<if test="ipAddress != null and ipAddress != ''">
AND ip_address = #{ipAddress}
</if>
<if test="creator != null and creator != ''">
AND creator = #{creator}
</if>
<if test="servce != null and servce != ''">
AND service = #{servce}
</if>
<if test="deptPath != null and deptPath != ''">
AND dept_path LIKE CONCAT(#{deptPath}, '%')
</if>
<if test="message != null and message != ''">
AND message LIKE CONCAT('%', #{message}, '%')
</if>
<if test="startTime != null">
AND create_time &gt;= #{startTime}
</if>
<if test="endTime != null">
AND create_time &lt;= #{endTime}
</if>
AND (deleted IS NULL OR deleted = false)
</where>
</select>
</mapper>

View File

@@ -0,0 +1,186 @@
<?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="org.xyzh.system.mapper.log.TbSysLoginLogMapper">
<!-- 结果映射 -->
<resultMap id="BaseResultMap" type="org.xyzh.api.system.dto.TbSysLoginLogDTO">
<id column="optsn" property="optsn" jdbcType="VARCHAR"/>
<result column="user_id" property="userId" jdbcType="VARCHAR"/>
<result column="username" property="username" jdbcType="VARCHAR"/>
<result column="ip_address" property="ipAddress" jdbcType="VARCHAR"/>
<result column="ip_source" property="ipSource" jdbcType="VARCHAR"/>
<result column="browser" property="browser" jdbcType="VARCHAR"/>
<result column="os" property="os" jdbcType="VARCHAR"/>
<result column="password" property="password" jdbcType="VARCHAR"/>
<result column="login_time" property="loginTime" jdbcType="TIMESTAMP"/>
<result column="status" property="status" jdbcType="INTEGER"/>
<result column="error_count" property="errorCount" jdbcType="INTEGER"/>
<result column="message" property="message" jdbcType="VARCHAR"/>
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
</resultMap>
<!-- 基础列 -->
<sql id="Base_Column_List">
optsn, user_id, username, ip_address, ip_source, browser, os, password,
login_time, status, error_count, message, create_time
</sql>
<!-- 插入系统登录日志 -->
<insert id="insertLoginLog" parameterType="org.xyzh.api.system.dto.TbSysLoginLogDTO">
INSERT INTO sys.tb_sys_login_log
<trim prefix="(" suffix=")" suffixOverrides=",">
optsn,
user_id,
username,
<if test="ipAddress != null and ipAddress != ''">ip_address,</if>
<if test="ipSource != null and ipSource != ''">ip_source,</if>
<if test="browser != null and browser != ''">browser,</if>
<if test="os != null and os != ''">os,</if>
<if test="password != null and password != ''">password,</if>
<if test="loginTime != null">login_time,</if>
<if test="status != null">status,</if>
<if test="errorCount != null">error_count,</if>
<if test="message != null and message != ''">message,</if>
<if test="createTime != null">create_time,</if>
</trim>
VALUES
<trim prefix="(" suffix=")" suffixOverrides=",">
#{optsn},
#{userId},
#{username},
<if test="ipAddress != null and ipAddress != ''">#{ipAddress},</if>
<if test="ipSource != null and ipSource != ''">#{ipSource},</if>
<if test="browser != null and browser != ''">#{browser},</if>
<if test="os != null and os != ''">#{os},</if>
<if test="password != null and password != ''">#{password},</if>
<if test="loginTime != null">#{loginTime},</if>
<if test="status != null">#{status},</if>
<if test="errorCount != null">#{errorCount},</if>
<if test="message != null and message != ''">#{message},</if>
<if test="createTime != null">#{createTime},</if>
</trim>
</insert>
<!-- 更新系统登录日志 -->
<update id="updateLoginLog" parameterType="org.xyzh.api.system.dto.TbSysLoginLogDTO">
UPDATE sys.tb_sys_login_log
<set>
<if test="userId != null and userId != ''">user_id = #{userId},</if>
<if test="username != null and username != ''">username = #{username},</if>
<if test="ipAddress != null and ipAddress != ''">ip_address = #{ipAddress},</if>
<if test="ipSource != null and ipSource != ''">ip_source = #{ipSource},</if>
<if test="browser != null and browser != ''">browser = #{browser},</if>
<if test="os != null and os != ''">os = #{os},</if>
<if test="password != null and password != ''">password = #{password},</if>
<if test="loginTime != null">login_time = #{loginTime},</if>
<if test="status != null">status = #{status},</if>
<if test="errorCount != null">error_count = #{errorCount},</if>
<if test="message != null and message != ''">message = #{message},</if>
</set>
WHERE optsn = #{optsn}
</update>
<!-- 删除系统登录日志 -->
<delete id="deleteLoginLog" parameterType="org.xyzh.api.system.dto.TbSysLoginLogDTO">
DELETE FROM sys.tb_sys_login_log
WHERE optsn = #{optsn}
</delete>
<!-- 根据登录日志ID查询系统登录日志 -->
<select id="getLoginLogById" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List" />
FROM sys.tb_sys_login_log
WHERE optsn = #{loginLogId}
</select>
<!-- 根据条件查询系统登录日志列表 -->
<select id="getLoginLogByFilter" resultMap="BaseResultMap" parameterType="org.xyzh.api.system.dto.TbSysLoginLogDTO">
SELECT <include refid="Base_Column_List" />
FROM sys.tb_sys_login_log
<where>
<if test="filter.optsn != null and filter.optsn != ''">
AND optsn = #{filter.optsn}
</if>
<if test="filter.userId != null and filter.userId != ''">
AND user_id = #{filter.userId}
</if>
<if test="filter.username != null and filter.username != ''">
AND username LIKE CONCAT('%', #{filter.username}, '%')
</if>
<if test="filter.ipAddress != null and filter.ipAddress != ''">
AND ip_address = #{filter.ipAddress}
</if>
<if test="filter.status != null">
AND status = #{filter.status}
</if>
<if test="filter.startTime != null">
AND login_time &gt;= #{filter.startTime}
</if>
<if test="filter.endTime != null">
AND login_time &lt;= #{filter.endTime}
</if>
</where>
ORDER BY login_time DESC
</select>
<!-- 根据条件查询系统登录日志分页列表 -->
<select id="getLoginLogPageByFilter" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List" />
FROM sys.tb_sys_login_log
<where>
<if test="filter.optsn != null and filter.optsn != ''">
AND optsn = #{filter.optsn}
</if>
<if test="filter.userId != null and filter.userId != ''">
AND user_id = #{filter.userId}
</if>
<if test="filter.username != null and filter.username != ''">
AND username LIKE CONCAT('%', #{filter.username}, '%')
</if>
<if test="filter.ipAddress != null and filter.ipAddress != ''">
AND ip_address = #{filter.ipAddress}
</if>
<if test="filter.status != null">
AND status = #{filter.status}
</if>
<if test="filter.startTime != null">
AND login_time &gt;= #{filter.startTime}
</if>
<if test="filter.endTime != null">
AND login_time &lt;= #{filter.endTime}
</if>
</where>
ORDER BY login_time DESC
LIMIT #{pageParam.pageSize} OFFSET #{pageParam.offset}
</select>
<!-- 根据条件查询系统登录日志数量 -->
<select id="getLoginLogCount" resultType="java.lang.Integer" parameterType="org.xyzh.api.system.dto.TbSysLoginLogDTO">
SELECT COUNT(1)
FROM sys.tb_sys_login_log
<where>
<if test="optsn != null and optsn != ''">
AND optsn = #{optsn}
</if>
<if test="userId != null and userId != ''">
AND user_id = #{userId}
</if>
<if test="username != null and username != ''">
AND username LIKE CONCAT('%', #{username}, '%')
</if>
<if test="ipAddress != null and ipAddress != ''">
AND ip_address = #{ipAddress}
</if>
<if test="status != null">
AND status = #{status}
</if>
<if test="startTime != null">
AND login_time &gt;= #{startTime}
</if>
<if test="endTime != null">
AND login_time &lt;= #{endTime}
</if>
</where>
</select>
</mapper>