Compare commits

...

49 Commits

Author SHA1 Message Date
yuejiajun
e961490e8b 追加调用方法名 2025-10-16 11:26:44 +08:00
yuejiajun
89a2d2bfd1 数据完整性校验 2025-10-16 11:14:44 +08:00
yuejiajun
60f6020c2c 飞书钩子 2025-10-15 18:20:38 +08:00
yuejiajun
d3432062b8 导出加密 2025-10-15 17:56:01 +08:00
yuejiajun
4f6b03cd53 导入导出通用实现 2025-10-15 17:02:21 +08:00
yuejiajun
091b281544 BaseController转为接口,追加导入导出通用方式 2025-10-15 17:01:18 +08:00
yuejiajun
3d15dfdc17 Controller相关 2025-10-15 11:13:38 +08:00
yuejiajun
f109c7713b WrapMapper 2025-10-14 19:32:45 +08:00
yuejiajun
1e9f808c4f 存储 2025-10-14 19:32:27 +08:00
yuejiajun
d20b2bdf99 自定义过滤使用 2025-09-30 16:02:52 +08:00
yuejiajun
beb6b074f7 自定义过滤功能 2025-09-30 16:02:42 +08:00
yuejiajun
abf472bcbb 分页查询分页问题 2025-09-30 14:19:40 +08:00
yuejiajun
dd67acf9c1 分页查询 2025-09-30 14:15:11 +08:00
yuejiajun
cfafe4574c 新增SQLite时间格式问题 2025-09-30 14:04:39 +08:00
yuejiajun
e0e0306577 查询详情 2025-09-30 13:49:25 +08:00
yuejiajun
02e8edbce7 修复 2025-09-30 13:22:29 +08:00
yuejiajun
9dab03231f 新增,时间问题解决了 2025-09-30 12:24:05 +08:00
yuejiajun
c6ce8eb246 新增 2025-09-30 11:55:04 +08:00
yuejiajun
3b55cde262 实体类增加链式功能 2025-09-30 11:50:27 +08:00
yuejiajun
786a361254 修复 字段不匹配问题,时间函数问题 2025-09-30 11:42:16 +08:00
yuejiajun
8a5de8e22a 修复 BaseServiceImpl 创建 Entity、VO、DTO 失败的问题 2025-09-30 11:22:13 +08:00
yuejiajun
e76ba43dab 调整 2025-09-30 11:13:13 +08:00
yuejiajun
03d7f90b9d util 2025-09-30 10:59:04 +08:00
yuejiajun
e82e2ef66f 恢复控制器 controller 2025-09-30 10:57:54 +08:00
yuejiajun
63230dd677 追加api3地址 2025-09-30 10:57:35 +08:00
yuejiajun
f9e832139f 启动初始化SQLite 2025-09-29 18:15:59 +08:00
yuejiajun
699c514c41 启动输出,h2 2025-09-29 18:00:10 +08:00
yuejiajun
46cb97b675 启动输出 2025-09-29 17:38:00 +08:00
yuejiajun
088dc1bf09 调整 2025-09-29 16:52:56 +08:00
yuejiajun
80bd441ee6 调整 2025-09-29 15:33:07 +08:00
yuejiajun
99adfdca80 测试方法与大地坐标系转化 2025-09-29 15:17:03 +08:00
yuejiajun
0043bc5bac 迁移 2025-09-29 14:58:32 +08:00
yuejiajun
91428f8a90 测试工具类 2025-09-29 14:28:05 +08:00
yuejiajun
2af0646d25 测试工具类 2025-09-29 13:14:21 +08:00
yuejiajun
b3dfb2102b 枚举 2025-09-29 11:41:38 +08:00
yuejiajun
2b58f2a8e6 枚举 2025-09-29 11:22:52 +08:00
yuejiajun
3402e89dd8 正则表达式直接替换 2025-09-29 10:47:24 +08:00
yuejiajun
7a5627add7 准备修复枚举 2025-09-29 10:40:29 +08:00
yuejiajun
6b1947d7ee 初始化 2025-09-29 10:00:12 +08:00
yuejiajun
c5ae3151ca 迁移 2025-09-28 17:57:40 +08:00
yuejiajun
50bd5f255d 调用自定义函数 2025-09-28 17:33:45 +08:00
yuejiajun
56fe8efe44 限制变量范围 2025-09-28 16:56:18 +08:00
yuejiajun
10a6da719f 测试类 2025-09-28 16:52:57 +08:00
yuejiajun
11586563a7 测试类 2025-09-28 15:26:09 +08:00
yuejiajun
cea42fdfbd 修复util 2025-09-28 15:06:51 +08:00
yuejiajun
42b3f26e73 修复正则替换、map排序 2025-09-28 14:47:29 +08:00
yuejiajun
445e3e2ad5 统计规则生效与未生效 2025-09-28 13:16:25 +08:00
yuejiajun
175fbf93a2 新增方法解析为 {{key}} 格式的 json 2025-09-28 12:01:37 +08:00
yuejiajun
03ab867c4f 追加注释 2025-09-28 10:20:16 +08:00
167 changed files with 12223 additions and 4514 deletions

13
pom.xml
View File

@ -258,8 +258,21 @@
<resource> <resource>
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
<includes> <includes>
<!-- jinjia2模板文件 -->
<include>**/**/*.j2</include> <include>**/**/*.j2</include>
<!-- Mapper文件、XML转化文件 -->
<include>**/*.xml</include> <include>**/*.xml</include>
<!-- 初始化脚本文件 -->
<include>**/*.sql</include>
<!-- 启动配置文件 -->
<include>**/*.yml</include>
<include>**/*.yaml</include>
<include>**/*.properties</include>
<!-- 静态资源 -->
<include>**/*.ico</include>
<include>**/*.css</include>
<include>**/*.js</include>
<include>**/*.html</include>
</includes> </includes>
<filtering>false</filtering> <filtering>false</filtering>
</resource> </resource>

View File

@ -13,8 +13,8 @@ import io.swagger.v3.oas.annotations.info.License;
* XML解析器应用程序主类 * XML解析器应用程序主类
* Spring Boot应用程序的入口点 * Spring Boot应用程序的入口点
* *
* @author system * @author 岳佳君 (2025年09月23日 16:53:14)
* @since 1.0.0 * @version 1.0.0
*/ */
@SpringBootApplication @SpringBootApplication
@MapperScan("com.example.demo.parser.mapper") // 扫描Mapper接口 @MapperScan("com.example.demo.parser.mapper") // 扫描Mapper接口

View File

@ -0,0 +1,4 @@
package com.example.demo.common.base;
public interface BaseListener {
}

View File

@ -0,0 +1,109 @@
package com.example.demo.common.base;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.env.Environment;
import org.springframework.context.ApplicationContext;
/**
* 启动输出接口
* 用于在SpringBoot启动后执行输出操作的Bean需要实现此接口
*
* @author 岳佳君 (2025年09月29日 16:45:39)
* @version 1.0.0
*/
public interface BaseStartupOutput extends CommandLineRunner {
/**
* 获取执行优先级数值越小优先级越高
*
* @return 执行优先级
*/
default int getOrder() {
return 0;
}
/**
* 是否启用该输出
*
* @return 是否启用
*/
default boolean isEnabled() {
return true;
}
/**
* 输出名称用于日志标识
*
* @return 输出名称
*/
default String getOutputName() {
return this.getClass().getSimpleName();
}
/**
* 获取服务器端口
*
* @param environment 环境配置
* @return 端口号
*/
default String getServerPort(Environment environment) {
return environment.getProperty("server.port", "8080");
}
/**
* 获取上下文路径
*
* @param environment 环境配置
* @return 上下文路径
*/
default String getContextPath(Environment environment) {
return environment.getProperty("server.servlet.context-path", "");
}
/**
* 获取基础URL
*
* @param environment 环境配置
* @return 基础URL
*/
default String getBaseUrl(Environment environment) {
String port = getServerPort(environment);
String path = getContextPath(environment);
return "http://localhost:" + port + path;
}
/**
* 获取完整的API URL
*
* @param environment 环境配置
* @param apiPath API路径
* @return 完整的API URL
*/
default String getApiUrl(Environment environment, String apiPath) {
String baseUrl = getBaseUrl(environment);
if (apiPath.startsWith("/")) {
return baseUrl + apiPath;
} else {
return baseUrl + "/" + apiPath;
}
}
/**
* 启动输出执行方法
*
* @param environment 环境配置
* @param context 应用上下文
*/
void outputOnStartup(Environment environment, ApplicationContext context);
/**
* CommandLineRunner接口的默认实现
*
* @param args 命令行参数
*/
@Override
default void run(String... args) {
// 由StartupOutputExecutor统一管理执行
}
}

View File

@ -0,0 +1,26 @@
package com.example.demo.common.base.startup.defaults;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
/**
* 启动默认输出
*
* @author 岳佳君 (2025年9月29日 17:26:23)
* @version 1.0.0
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class StartupOutput implements com.example.demo.common.base.BaseStartupOutput {
@Override
public void outputOnStartup(Environment environment, ApplicationContext context) {
// 获取当前激活的环境如devtestprod
String[] activeProfiles = environment.getActiveProfiles();
String activeProfile = activeProfiles.length > 0 ? activeProfiles[0] : "default";
log.info("当前环境: {}", activeProfile);
}
}

View File

@ -0,0 +1,83 @@
package com.example.demo.common.base.startup.executor;
import com.example.demo.common.base.BaseStartupOutput;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* 启动输出执行器
* 统一管理所有BaseStartupOutput实现类的执行
*
* @author 岳佳君 (2025年9月29日 17:18:32)
* @version 1.0.0
*/
@Slf4j
@Component
public class StartupOutputExecutor implements ApplicationRunner {
private final List<BaseStartupOutput> outputs;
private final Environment environment;
private final ApplicationContext context;
/**
* 构造函数
*
* @param outputs 所有BaseStartupOutput实现类可选依赖
* @param environment 环境配置
* @param context 应用上下文
*/
public StartupOutputExecutor(List<BaseStartupOutput> outputs,
Environment environment,
ApplicationContext context) {
this.outputs = outputs != null ? outputs : Collections.emptyList();
this.environment = environment;
this.context = context;
}
/**
* 执行所有启动输出
*
* @param args 应用参数
*/
@Override
public void run(ApplicationArguments args) {
if (outputs.isEmpty()) {
log.debug("未发现需要执行的启动输出");
return;
}
log.debug("开始执行启动输出,共发现 {} 个输出组件", outputs.size());
// 按优先级排序并执行
outputs.stream()
.filter(BaseStartupOutput::isEnabled)
.sorted(Comparator.comparingInt(BaseStartupOutput::getOrder))
.forEach(this::executeOutput);
log.debug("启动输出执行完成");
}
/**
* 执行单个输出组件
*
* @param output 输出组件
*/
private void executeOutput(BaseStartupOutput output) {
String outputName = output.getOutputName();
try {
log.trace("执行启动输出: {}", outputName);
output.outputOnStartup(environment, context);
log.trace("启动输出执行成功: {}", outputName);
} catch (Exception e) {
log.warn("启动输出执行失败: {}", outputName, e);
}
}
}

View File

@ -0,0 +1,46 @@
package com.example.demo.common.base.startup.output;
import com.example.demo.common.base.BaseStartupOutput;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* API文档地址输出
* 在启动后输出API文档访问地址
*
* @author 岳佳君 (2025年09月29日 16:45:00)
* @version 1.0.0
*/
@Slf4j
@Component
public class ApiDocOutput implements BaseStartupOutput {
/**
* 获取执行优先级
*
* @return 优先级数值越小优先级越高
*/
@Override
public int getOrder() {
return 10;
}
/**
* 启动输出执行方法
*
* @param environment 环境配置
* @param context 应用上下文
*/
@Override
public void outputOnStartup(Environment environment, ApplicationContext context) {
// 使用接口提供的通用方法获取API文档地址
String apiDocUrl = getApiUrl(environment, "/doc.html");
String api3Url = getApiUrl(environment, "/v3/api-docs");
System.out.println("📚 API文档地址:");
System.out.println(" • Knife4j文档: " + apiDocUrl);
System.out.println(" • API3文档: " + api3Url);
log.trace("API文档地址输出完成 - Knife4j: {} - API3: {}", apiDocUrl, api3Url);
}
}

View File

@ -0,0 +1,154 @@
package com.example.demo.common.base.startup.output;
import com.example.demo.common.base.BaseStartupOutput;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
/**
* H2数据库控制台地址和连通情况输出
* 在启动后输出H2控制台访问地址并检查数据库连通情况
* 仅在h2激活环境下生效
*
* @author 岳佳君 (2025年09月29日 16:45:00)
* @version 1.0.0
*/
@Slf4j
@Component
public class H2Output implements BaseStartupOutput {
/**
* 获取执行优先级
*
* @return 优先级数值越小优先级越高
*/
@Override
public int getOrder() {
return 8;
}
/**
* 检查是否启用H2输出
* 仅在h2激活环境下生效
*
* @return 是否启用
*/
@Override
public boolean isEnabled() {
return true; // 由outputOnStartup方法内部检查环境
}
/**
* 启动输出执行方法
*
* @param environment 环境配置
* @param context 应用上下文
*/
@Override
public void outputOnStartup(Environment environment, ApplicationContext context) {
// 检查是否在h2激活环境下
if (!isH2Active(environment)) {
log.debug("H2环境未激活跳过H2控制台输出");
return;
}
System.out.println("💾 H2数据库信息:");
// 输出H2控制台地址
String h2ConsoleUrl = getApiUrl(environment, "/h2-console");
System.out.println(" • H2控制台地址: " + h2ConsoleUrl);
// 检查H2数据库连通情况
checkH2Connection(context);
}
/**
* 检查H2环境是否激活
*
* @param environment 环境配置
* @return 是否激活
*/
private boolean isH2Active(Environment environment) {
String[] activeProfiles = environment.getActiveProfiles();
for (String profile : activeProfiles) {
if ("h2".equalsIgnoreCase(profile)) {
return true;
}
}
// 检查是否配置了H2数据源
String h2Url = environment.getProperty("spring.datasource.h2.url");
String h2Enabled = environment.getProperty("spring.h2.console.enabled");
return h2Url != null || "true".equals(h2Enabled);
}
/**
* 检查H2数据库连通情况
*
* @param context 应用上下文
*/
private void checkH2Connection(ApplicationContext context) {
try {
// 尝试获取H2数据源
DataSource h2DataSource = null;
// 首先尝试按名称获取
if (context.containsBean("h2DataSource")) {
h2DataSource = context.getBean("h2DataSource", DataSource.class);
} else if (context.containsBean("dataSource")) {
// 尝试获取默认数据源
DataSource dataSource = context.getBean("dataSource", DataSource.class);
// 检查是否是H2数据源
String url = getDataSourceUrl(dataSource);
if (url != null && url.contains(":h2:")) {
h2DataSource = dataSource;
}
}
if (h2DataSource != null) {
try (Connection connection = h2DataSource.getConnection()) {
if (connection.isValid(5)) {
System.out.println(" • H2数据库连接: ✅ 正常");
log.debug("H2数据库连接正常");
} else {
System.out.println(" • H2数据库连接: ❌ 无效");
log.warn("H2数据库连接无效");
}
}
} else {
System.out.println(" • H2数据库连接: ⚠️ 未配置");
log.info("H2数据库未配置");
}
} catch (SQLException e) {
System.out.println(" • H2数据库连接: ❌ 失败 - " + e.getMessage());
log.error("H2数据库连接失败: {}", e.getMessage());
} catch (Exception e) {
System.out.println(" • H2数据库连接: ❌ 检查失败 - " + e.getMessage());
log.error("H2数据库检查失败: {}", e.getMessage());
}
}
/**
* 获取数据源的URL
*
* @param dataSource 数据源
* @return URL字符串
*/
private String getDataSourceUrl(DataSource dataSource) {
try {
// 尝试通过连接获取URL
try (Connection connection = dataSource.getConnection()) {
return connection.getMetaData().getURL();
}
} catch (Exception e) {
log.debug("无法获取数据源URL: {}", e.getMessage());
return null;
}
}
}

View File

@ -1,49 +0,0 @@
//package com.example.demo.common.config;
//
//import lombok.RequiredArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.boot.CommandLineRunner;
//import org.springframework.core.io.ClassPathResource;
//import org.springframework.jdbc.datasource.init.ScriptUtils;
//import org.springframework.stereotype.Component;
//
//import javax.sql.DataSource;
//import java.sql.Connection;
//
///**
// * 数据库初始化配置
// * 应用启动时自动执行数据库脚本
// *
// * @author system
// * @version 1.0
// */
//@Slf4j
//@Component
//@RequiredArgsConstructor
//public class DatabaseInitializer implements CommandLineRunner {
//
// private final DataSource dataSource;
//
// /**
// * 应用启动时执行数据库初始化
// *
// * @param args 命令行参数
// * @throws Exception 异常
// */
// @Override
// public void run(String... args) throws Exception {
// log.info("开始初始化数据库...");
//
// try (Connection connection = dataSource.getConnection()) {
// // 执行数据库初始化脚本
// ClassPathResource schemaResource = new ClassPathResource("schema.sql");
// ScriptUtils.executeSqlScript(connection, schemaResource);
//
// log.info("数据库初始化完成");
// } catch (Exception e) {
// log.error("数据库初始化失败: {}", e.getMessage(), e);
// throw new RuntimeException("数据库初始化失败", e);
// }
// log.info("应用启动成功....");
// }
//}

View File

@ -1,4 +1,4 @@
package com.example.demo.common.config; package com.example.demo.common.config.database;
import com.example.demo.common.constant.GlobalConstants; import com.example.demo.common.constant.GlobalConstants;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -13,8 +13,8 @@ import java.util.concurrent.TimeUnit;
* 缓存配置类 * 缓存配置类
* 配置H2内存缓存用于缓存解析规则和映射规则等数据 * 配置H2内存缓存用于缓存解析规则和映射规则等数据
* *
* @author system * @author 岳佳君 (2025年09月24日 17:30:09)
* @version 1.0 * @version 1.0.0
*/ */
@Configuration @Configuration
@EnableCaching @EnableCaching

View File

@ -0,0 +1,54 @@
package com.example.demo.common.config.database.initializer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.init.ScriptUtils;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.sql.Connection;
/**
* 数据库初始化配置
* 应用启动时自动执行数据库脚本包括创建表结构插入初始数据等
* 仅在SQLite数据源存在时生效
*
* @author 岳佳君 (2025年09月25日 15:00:27)
* @version 1.0.0
*/
@Slf4j
@Component
@RequiredArgsConstructor
@ConditionalOnBean(name = "sqliteDataSource")
public class DatabaseInitializer implements CommandLineRunner {
private final static String baseURL = "script/sqlite/";
private final DataSource dataSource;
/**
* 应用启动时执行数据库初始化
*
* @param args 命令行参数
* @throws Exception 初始化过程中可能抛出的异常
*/
@Override
public void run(String... args) throws Exception {
log.info("开始初始化数据库...");
try (Connection connection = dataSource.getConnection()) {
// 执行数据库初始化脚本
ClassPathResource schemaResource = new ClassPathResource(baseURL + "sqlite-schema.sql");
ScriptUtils.executeSqlScript(connection, schemaResource);
log.info("{} 数据库初始化完成", connection.getMetaData().getURL());
} catch (Exception e) {
log.error("数据库初始化失败: {}", e.getMessage(), e);
throw new RuntimeException("数据库初始化失败", e);
}
log.info("应用启动成功....");
}
}

View File

@ -1,4 +1,4 @@
package com.example.demo.common.config; package com.example.demo.common.config.database.real;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
@ -15,8 +15,9 @@ import javax.sql.DataSource;
* H2数据源配置类 * H2数据源配置类
* 配置缓存数据库H2的数据源和初始化 * 配置缓存数据库H2的数据源和初始化
* *
* @author system * @author 岳佳君 (2025年09月25日 18:41:00)
* @since 1.0.0 * @since 1.0.0
* @version 1.0.0
*/ */
@Configuration @Configuration
public class H2DataSourceConfig { public class H2DataSourceConfig {

View File

@ -1,4 +1,4 @@
package com.example.demo.common.config; package com.example.demo.common.config.database.real;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
@ -16,8 +16,8 @@ import javax.sql.DataSource;
* SQLite数据源配置类 * SQLite数据源配置类
* 配置主数据库SQLite的数据源和初始化 * 配置主数据库SQLite的数据源和初始化
* *
* @author system * @author 岳佳君 (2025年09月24日 20:13:04)
* @since 1.0.0 * @version 1.0.0
*/ */
@Configuration @Configuration
public class SqliteDataSourceConfig { public class SqliteDataSourceConfig {

View File

@ -6,8 +6,8 @@ import org.springframework.context.annotation.Configuration;
* Bean Searcher配置类 * Bean Searcher配置类
* 配置Bean Searcher框架用于高级查询功能 * 配置Bean Searcher框架用于高级查询功能
* *
* @author system * @author 岳佳君 (2025年09月23日 16:28:52)
* @version 1.0 * @version 1.0.0
*/ */
@Configuration @Configuration
public class BeanSearcherConfig { public class BeanSearcherConfig {

View File

@ -0,0 +1,65 @@
package com.example.demo.common.config.orm.handler;
import cn.zhxu.bs.FieldConvertor;
import cn.zhxu.bs.FieldMeta;
import cn.zhxu.bs.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Bean Searcher 日期字段转换器
* 用于处理数据库字符串到 Date 类型的转换
*
* @author 岳佳君 (2025年09月30日 13:30:00)
* @version 1.0.0
*/
@Slf4j
public class DateFieldConvertor implements FieldConvertor.BFieldConvertor {
/**
* 支持的源类型
*/
@Override
public boolean supports(FieldMeta meta, Class<?> valueType) {
// 支持从 String 类型转换为 Date 类型
return String.class.equals(valueType) && Date.class.equals(meta.getType());
}
/**
* 转换方法
*/
@Override
public Object convert(FieldMeta meta, Object value) {
if (value == null || StringUtils.isBlank(value.toString())) {
return null;
}
String dateStr = value.toString().trim();
// 尝试多种日期格式进行解析
String[] patterns = {
"yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd_HH:mm:ss",
"yyyy-MM-dd",
"yyyy/MM/dd HH:mm:ss",
"yyyy/MM/dd"
};
for (String pattern : patterns) {
try {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
sdf.setLenient(false); // 严格模式
return sdf.parse(dateStr);
} catch (ParseException e) {
// 尝试下一种格式
continue;
}
}
// 如果所有格式都解析失败返回 null
return null;
}
}

View File

@ -0,0 +1,69 @@
package com.example.demo.common.config.orm.handler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* SQLite 日期类型处理器
* Java Date 对象转换为 SQLite 支持的日期字符串格式
*
* @author 岳佳君 (2025年09月24日 17:40:34)
* @version 1.0.0
*/
public class SqliteDateTypeHandler implements TypeHandler<Date> {
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public void setParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType) throws SQLException {
if (parameter == null) {
ps.setNull(i, Types.VARCHAR);
} else {
// Date 转换为 SQLite 支持的日期字符串格式
String dateString = DATE_FORMAT.format(parameter);
ps.setString(i, dateString);
}
}
@Override
public Date getResult(ResultSet rs, String columnName) throws SQLException {
String dateString = rs.getString(columnName);
return parseDate(dateString);
}
@Override
public Date getResult(ResultSet rs, int columnIndex) throws SQLException {
String dateString = rs.getString(columnIndex);
return parseDate(dateString);
}
@Override
public Date getResult(CallableStatement cs, int columnIndex) throws SQLException {
String dateString = cs.getString(columnIndex);
return parseDate(dateString);
}
/**
* 解析日期字符串为 Date 对象
*
* @param dateString 日期字符串
* @return Date 对象
*/
private Date parseDate(String dateString) {
if (dateString == null || dateString.trim().isEmpty()) {
return null;
}
try {
// 尝试解析 yyyy-MM-dd HH:mm:ss 格式
return DATE_FORMAT.parse(dateString);
} catch (Exception e) {
// 如果解析失败尝试其他格式或返回当前时间
return new Date();
}
}
}

View File

@ -0,0 +1,62 @@
package com.example.demo.common.config.orm.listener;
import com.mybatisflex.annotation.InsertListener;
import com.mybatisflex.annotation.SetListener;
import com.mybatisflex.annotation.UpdateListener;
import com.example.demo.common.domain.BaseEntity;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
/**
* 时间戳监听器
* 用于在插入和更新操作时自动设置创建时间和更新时间
*
* @author 岳佳君 (2025年09月24日 17:40:34)
* @version 1.0.0
*/
@Slf4j
public class FlexListener implements InsertListener, UpdateListener, SetListener {
/**
* 插入前监听
* 设置创建时间和更新时间
*
* @param entity 实体对象
*/
@Override
public void onInsert(Object entity) {
log.info("--------------------------------- onInsert");
if (entity instanceof BaseEntity baseEntity) {
Date now = new Date();
// 设置创建时间如果为空
if (baseEntity.getCreatedTime() == null) {
baseEntity.setCreatedTime(now);
}
// 设置更新时间
baseEntity.setUpdatedTime(now);
}
}
/**
* 更新前监听
* 设置更新时间
*
* @param entity 实体对象
*/
@Override
public void onUpdate(Object entity) {
log.info("--------------------------------- onUpdate");
if (entity instanceof BaseEntity baseEntity) {
// 设置更新时间
baseEntity.setUpdatedTime(new Date());
}
}
@Override
public Object onSet(Object entity, String property, Object value) {
return value;
}
}

View File

@ -10,8 +10,8 @@ import org.springframework.context.annotation.Configuration;
* OpenAPI配置类 * OpenAPI配置类
* 配置Swagger/OpenAPI文档生成 * 配置Swagger/OpenAPI文档生成
* *
* @author system * @author 岳佳君 (2025年09月26日 13:33:14)
* @version 1.0 * @version 1.0.0
*/ */
@Configuration @Configuration
@OpenAPIDefinition( @OpenAPIDefinition(

View File

@ -37,8 +37,8 @@ import java.io.InputStream;
* } * }
* </pre> * </pre>
* *
* @author system * @author 岳佳君 (2025年09月25日 23:42:44)
* @version 1.0 * @version 1.0.0
* *
* @see Tika * @see Tika
* @see TikaConfig * @see TikaConfig

View File

@ -15,8 +15,8 @@ import java.nio.charset.Charset;
* 主要用于识别文件或数据流的字符集如UTF-8GBKISO-8859-1等 * 主要用于识别文件或数据流的字符集如UTF-8GBKISO-8859-1等
* </p> * </p>
* *
* @author system * @author 岳佳君 (2025年09月25日 23:42:44)
* @version 1.0 * @version 1.0.0
*/ */
@Slf4j @Slf4j
public class FileCharsetCheck { public class FileCharsetCheck {

View File

@ -16,8 +16,8 @@ import java.util.List;
* 使用Apache Tika库检测文件真实类型防止文件类型欺骗攻击 * 使用Apache Tika库检测文件真实类型防止文件类型欺骗攻击
* 通过白名单机制限制可上传的文件类型增强系统安全性 * 通过白名单机制限制可上传的文件类型增强系统安全性
* *
* @author system * @author 岳佳君 (2025年09月25日 23:42:44)
* @version 1.0 * @version 1.0.0
*/ */
@Slf4j @Slf4j
public class FileTypeCheck { public class FileTypeCheck {

View File

@ -8,8 +8,8 @@ package com.example.demo.common.config.tika.handle;
* 参考了标准MIME类型定义及常见文件格式:cite[2]:cite[9] * 参考了标准MIME类型定义及常见文件格式:cite[2]:cite[9]
* </p> * </p>
* *
* @author system * @author 岳佳君 (2025年09月25日 23:42:44)
* @version 1.0 * @version 1.0.0
*/ */
public class FileTypeConst { public class FileTypeConst {

View File

@ -0,0 +1,13 @@
package com.example.demo.common.config.web;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// ignore
}
}

View File

@ -4,8 +4,8 @@ package com.example.demo.common.constant;
* 系统常量类 * 系统常量类
* 定义系统中使用的各种常量包括错误码文件类型状态码等 * 定义系统中使用的各种常量包括错误码文件类型状态码等
* *
* @author system * @author 岳佳君 (2025年09月24日 19:16:15)
* @version 1.0 * @version 1.0.0
*/ */
public class GlobalConstants { public class GlobalConstants {

View File

@ -1,7 +1,9 @@
package com.example.demo.common.domain; package com.example.demo.common.domain;
import com.mybatisflex.annotation.Column;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.io.Serial; import java.io.Serial;
@ -12,13 +14,14 @@ import java.util.Date;
* 基础数据传输对象 * 基础数据传输对象
* 所有DTO类的基类用于数据在不同层之间的传递 * 所有DTO类的基类用于数据在不同层之间的传递
* *
* @author system * @author 岳佳君 (2025年09月24日 18:29:58)
* @version 1.0 * @version 1.0.0
*/ */
@Schema(description = "基础数据传输对象") @Schema(description = "基础数据传输对象")
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class BaseDTO implements Serializable { public class BaseDTO implements Serializable {
@ -33,26 +36,42 @@ public class BaseDTO implements Serializable {
private String id; private String id;
/** /**
* 创建时间 * 名称
*/ */
@Schema(description = "创建时间") @Schema(description = "名称")
private Date createdTime; private String name;
/** /**
* 创建人ID * 命名空间
*/ */
@Schema(description = "创建人ID") @Schema(description = "命名空间")
private String createdId; private String nameSpace;
/** /**
* 更新时间 * 排序字段
*/ */
@Schema(description = "更新时间") @Schema(description = "排序字段")
private Date updatedTime; private String sortName;
/** /**
* 更新人ID * 是否删除0未删除1已删除
*/ */
@Schema(description = "更新人ID") @Column(isLogicDelete = true)
private String updatedId; @Schema(description = "是否删除")
private Integer isDelete;
/**
* 乐观锁版本号
*/
@Column(version = true)
@Schema(description = "乐观锁版本号")
private Integer revision;
// 创建时间创建ID更新时间更新ID不允许前端或API直接控制
/**
* 租户ID
*/
@Schema(description = "租户ID")
private String tenantId;
} }

View File

@ -1,11 +1,15 @@
package com.example.demo.common.domain; package com.example.demo.common.domain;
import com.example.demo.common.config.orm.handler.SqliteDateTypeHandler;
import com.example.demo.common.config.orm.listener.FlexListener;
import com.mybatisflex.annotation.Column; import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id; import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType; import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import com.mybatisflex.core.keygen.KeyGenerators; import com.mybatisflex.core.keygen.KeyGenerators;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
@ -19,15 +23,23 @@ import java.util.Date;
* 基础实体类 * 基础实体类
* 所有数据库实体类的基类包含通用字段和注解 * 所有数据库实体类的基类包含通用字段和注解
* *
* @author system * @author 岳佳君 (2025年09月24日 17:40:34)
* @version 1.0 * @version 1.0.0
*/ */
@Schema(description = "基础实体类") @Schema(description = "基础实体类")
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Table(
value = "demo",
comment = "基本类没有对应的表!",
onInsert = FlexListener.class,
onUpdate = FlexListener.class,
onSet = FlexListener.class
)
public class BaseEntity implements Serializable { public class BaseEntity implements Serializable {
@Serial @Serial
@ -40,6 +52,12 @@ public class BaseEntity implements Serializable {
@Schema(description = "ID") @Schema(description = "ID")
private String id; private String id;
/**
* 名称
*/
@Schema(description = "名称")
private String name;
/** /**
* 命名空间 * 命名空间
*/ */
@ -56,8 +74,8 @@ public class BaseEntity implements Serializable {
* 是否删除0未删除1已删除 * 是否删除0未删除1已删除
*/ */
@Column(isLogicDelete = true) @Column(isLogicDelete = true)
@Schema(description = "是否删除") @Schema(description = "是否删除")
private String isDelete; private Integer isDeleted;
/** /**
* 乐观锁版本号 * 乐观锁版本号
@ -68,8 +86,13 @@ public class BaseEntity implements Serializable {
/** /**
* 创建时间 * 创建时间
* <p>
* <hr/>
* Column(onInsertValue = "now()")
* Column(onInsertValue = "CURRENT_TIMESTAMP")
* Column(onInsertValue = "datetime('now', 'localtime')")
*/ */
@Column(onInsertValue = "now()") @Column(typeHandler = SqliteDateTypeHandler.class)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Schema(description = "创建时间") @Schema(description = "创建时间")
@ -83,8 +106,13 @@ public class BaseEntity implements Serializable {
/** /**
* 更新时间 * 更新时间
* <p>
* <hr/>
* Column(onUpdateValue = "now()", onInsertValue = "now()")
* Column(onUpdateValue = "CURRENT_TIMESTAMP", onInsertValue = "CURRENT_TIMESTAMP")
* Column(onUpdateValue = "datetime('now', 'localtime')", onInsertValue = "datetime('now', 'localtime')")
*/ */
@Column(onUpdateValue = "now()", onInsertValue = "now()") @Column(typeHandler = SqliteDateTypeHandler.class)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Schema(description = "更新时间") @Schema(description = "更新时间")

View File

@ -1,8 +1,10 @@
package com.example.demo.common.domain; package com.example.demo.common.domain;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.*; import lombok.*;
import cn.zhxu.bs.bean.DbField; import cn.zhxu.bs.bean.DbField;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.io.Serial; import java.io.Serial;
@ -13,13 +15,14 @@ import java.util.Date;
* 基础查询数据传输对象 * 基础查询数据传输对象
* 所有查询DTO类的基类用于封装查询条件 * 所有查询DTO类的基类用于封装查询条件
* *
* @author system * @author 岳佳君 (2025年09月23日 17:41:39)
* @version 1.0 * @version 1.0.0
*/ */
@Schema(description = "基础查询数据传输对象") @Schema(description = "基础查询数据传输对象")
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class BaseQueryDTO implements Serializable { public class BaseQueryDTO implements Serializable {
@ -59,4 +62,8 @@ public class BaseQueryDTO implements Serializable {
@Schema(description = "排序方式") @Schema(description = "排序方式")
private String sortOrder; private String sortOrder;
@NotNull(message = "页码不能为空")
public int getPageNum() {
return (this.pageNum - 1) * pageSize;
}
} }

View File

@ -1,26 +1,27 @@
package com.example.demo.common.domain; package com.example.demo.common.domain;
import com.mybatisflex.annotation.Column; import cn.zhxu.bs.bean.DbIgnore;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
/** /**
* 基础视图对象 * 基础视图对象
* 所有VO类的基类用于向前端返回数据 * 所有VO类的基类用于向前端返回数据
* *
* @author system * @author 岳佳君 (2025年09月24日 10:07:13)
* @version 1.0 * @version 1.0.0
*/ */
@Schema(description = "基础视图对象") @Schema(description = "基础视图对象")
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class BaseVO implements Serializable { public class BaseVO implements Serializable {
@ -37,13 +38,14 @@ public class BaseVO implements Serializable {
/** /**
* *
*/ */
@Schema(description = "key") @DbIgnore
@Schema(description = "")
private String key; private String key;
/** /**
* 名称 * 名称
*/ */
@Schema(description = "name") @Schema(description = "名称")
private String name; private String name;
/** /**
@ -51,11 +53,12 @@ public class BaseVO implements Serializable {
*/ */
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Schema(description = "创建时间") @Schema(description = "创建时间")
private Date createdTime; private String createdTime;
/** /**
* 创建人ID * 创建人ID
*/ */
@DbIgnore
@Schema(description = "创建人ID") @Schema(description = "创建人ID")
private String createdId; private String createdId;
@ -64,11 +67,12 @@ public class BaseVO implements Serializable {
*/ */
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Schema(description = "更新时间") @Schema(description = "更新时间")
private Date updatedTime; private String updatedTime;
/** /**
* 更新人ID * 更新人ID
*/ */
@DbIgnore
@Schema(description = "更新人ID") @Schema(description = "更新人ID")
private String updatedId; private String updatedId;
@ -76,5 +80,5 @@ public class BaseVO implements Serializable {
* 是否删除0未删除1已删除 * 是否删除0未删除1已删除
*/ */
@Schema(description = "是否删除") @Schema(description = "是否删除")
private String isDelete; private Integer isDeleted;
} }

View File

@ -0,0 +1,149 @@
package com.example.demo.common.domain;
import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
import java.io.Serializable;
import java.security.MessageDigest;
import java.util.Objects;
/**
* 导入导出加密传输对象
* 用于封装导入导出的统一数据结构
*
* @author 岳佳君 (2025年10月15日 16:29:01)
* @version 1.0.0
*/
@Schema(description = "导入导出加密传输对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
public class BaseXPortData implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@Schema(description = "ID")
private String id;
/**
* 时间戳
*/
@Schema(description = "时间戳")
private String ts;
/**
* 签名 sign
*/
@Schema(description = "签名")
private String s;
/**
* 完整性 gritty cvedata 四种数据组成 sha1 做完整性校验
*/
@Schema(description = "完整性")
private String g;
/**
* 版本 version
*/
@Schema(description = "版本")
private String v;
/**
* 类名 clazz通过字符串加密记录处理的 data class 对象
*/
@Schema(description = "类名")
private String c;
/**
* 类名 service通过字符串加密记录处理的 service 字段名
*/
@Schema(description = "服务名")
private String e;
/**
* 服务方法名 method通过字符串加密记录处理的 service#method 字段名
*/
@Schema(description = "服务方法名")
private String m;
/**
* 数据通过字符串加密记录实际数据
*/
@Schema(description = "数据")
private String data;
/**
* 获取校验和
* @return 为空则进行计算
*/
public String getG() {
return g == null || g.trim().isEmpty() ? (generateChecksum(c, v, e, m, data)) : (g);
}
/**
* 生成数据的校验和
*/
public static String generateChecksum(String c, String v, String e, String m, String data) {
try {
String combined = c + "|" + v + "|" + e + "|" + m + "|" + data;
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(combined.getBytes());
@SuppressWarnings("all")
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (Exception ex) {
throw new RuntimeException("生成校验和失败", ex);
}
}
/**
* 验证数据完整性
*/
public static boolean verifyIntegrity(String c, String v, String e, String m, String data, String expectedChecksum) {
String actualChecksum = generateChecksum(c, v, e, m, data);
return Objects.equals(actualChecksum, expectedChecksum);
}
/**
* 验证数据完整性
*/
public boolean verifyIntegrity() {
return verifyIntegrity(c, v, e, m, data, g);
}
public static void main(String[] args) {
BaseXPortData baseXPortData = new BaseXPortData();
baseXPortData.id = "1";
baseXPortData.ts = "1";
baseXPortData.data = "123";
System.out.println("check: " + baseXPortData.getG());
String json = JSON.toJSONString(baseXPortData);
System.out.println("json: " + json);
BaseXPortData baseXPortData1 = JSON.parseObject(json, BaseXPortData.class);
baseXPortData1.data = "1234";
System.out.println("verifyIntegrity: " + baseXPortData1.verifyIntegrity());
}
}

View File

@ -10,8 +10,8 @@ import java.io.Serial;
* 业务异常类 * 业务异常类
* 用于表示业务逻辑中的异常情况 * 用于表示业务逻辑中的异常情况
* *
* @author system * @author 岳佳君 (2025年09月25日 14:22:43)
* @version 1.0 * @version 1.0.0
*/ */
@Getter @Getter
@Setter(value = AccessLevel.PRIVATE) @Setter(value = AccessLevel.PRIVATE)

View File

@ -23,8 +23,8 @@ import java.util.stream.Collectors;
* 全局异常处理器 * 全局异常处理器
* 统一处理系统异常返回规范的错误响应 * 统一处理系统异常返回规范的错误响应
* *
* @author system * @author 岳佳君 (2025年09月25日 17:37:47)
* @version 1.0 * @version 1.0.0
*/ */
@Slf4j @Slf4j
@RestControllerAdvice @RestControllerAdvice

View File

@ -0,0 +1,74 @@
package com.example.demo.common.filter;
import lombok.extern.slf4j.Slf4j;
import java.util.*;
@Slf4j
public class CustomJsonFilter {
@SuppressWarnings("all")
@Override
public boolean equals(Object obj) {
if (obj == null) {
return true;
}
boolean flag = !shouldInclude(obj);
log.trace("{} => {}", flag, obj);
return flag;
}
/**
* 判断值是否应该被包含
*/
private boolean shouldInclude(Object value) {
// 处理空字符串
if (value instanceof CharSequence) {
return !((CharSequence) value).isEmpty();
}
// 处理空集合
if (value instanceof Collection) {
return !((Collection<?>) value).isEmpty();
}
// 处理空Map
if (value instanceof Map) {
return !((Map<?, ?>) value).isEmpty();
}
// 处理空数组
if (value instanceof Object[]) {
return ((Object[]) value).length > 0;
}
// 处理基本类型数组
if (value instanceof int[]) {
return ((int[]) value).length > 0;
}
if (value instanceof long[]) {
return ((long[]) value).length > 0;
}
if (value instanceof double[]) {
return ((double[]) value).length > 0;
}
if (value instanceof boolean[]) {
return ((boolean[]) value).length > 0;
}
if (value instanceof char[]) {
return ((char[]) value).length > 0;
}
if (value instanceof byte[]) {
return ((byte[]) value).length > 0;
}
if (value instanceof float[]) {
return ((float[]) value).length > 0;
}
// 处理空Optional
if (value instanceof Optional) {
return ((Optional<?>) value).isPresent();
}
// 其他对象类型只要不为null就包含
return true;
}
}

View File

@ -1,11 +1,226 @@
package com.example.demo.common.typography; package com.example.demo.common.typography;
import cn.zhxu.bs.SearchResult;
import com.example.demo.common.domain.BaseDTO;
import com.example.demo.common.domain.BaseQueryDTO;
import com.example.demo.common.domain.BaseVO;
import com.example.demo.common.exception.BusinessException;
import com.example.demo.common.wrapper.WrapMapper;
import com.example.demo.common.wrapper.Wrapper;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.springframework.web.multipart.MultipartFile;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* 统一 Controller 接口 * 统一 Controller 接口
* 统一定义 Controller 基础接口 * 统一定义 Controller 基础接口包含通用的CRUD操作
* *
* @author system * @param <VO> 视图对象类型
* @version 1.0 * @param <DTO> 数据传输对象类型
* @param <QueryDTO> 数据传输查询对象类型
* @param <SERVICE> 服务层类型
* @author 岳佳君 (2025年09月25日 22:42:44)
* @version 1.0.0
*/ */
public abstract class BaseController { @SuppressWarnings("all")
public interface BaseController<
SERVICE extends BaseService,
DTO extends BaseDTO,
QueryDTO extends BaseQueryDTO,
VO extends BaseVO> {
/**
* 获取服务层实例
* <p>
* 子类必须实现此方法返回对应的服务层实例用于执行具体的业务操作
* </p>
*
* @return 服务层实例继承自BaseService
*/
public SERVICE getService();
/**
* 获取操作名称
* <p>
* 子类必须实现此方法返回当前操作的中文名称用于日志记录和错误信息提示
* </p>
*
* @return 操作名称"用户""角色"
*/
public String getOperationName();
/**
* 获取操作名称
* <p>
* 子类必须实现此方法返回当前操作的中文名称用于日志记录和错误信息提示
* </p>
*
* @return 操作名称"用户""角色"
*/
public Logger getLog();
/**
* 创建对象的通用方法
*
* @param dto 数据传输对象
* @return 操作结果包装对象
*/
default public Wrapper<VO> create(DTO dto) {
try {
return (Wrapper<VO>) WrapMapper.ok(getService().create(dto));
} catch (BusinessException e) {
getLog().error("{}创建失败: {}", getOperationName(), e.getMessage(), e);
return WrapMapper.error(e.getMessage());
} catch (Exception e) {
getLog().error("{}创建异常: {}", getOperationName(), e.getMessage(), e);
return WrapMapper.error(getOperationName() + "创建失败");
}
}
/**
* 更新对象的通用方法
*
* @param dto 数据传输对象
* @return 操作结果包装对象
*/
default public Wrapper<VO> update(DTO dto) {
try {
getService().update(dto);
// 假设DTO有getId方法
VO result = (VO) getService().detail(getIdFromDto(dto));
return WrapMapper.ok(result);
} catch (BusinessException e) {
getLog().error("{}更新失败: {}", getOperationName(), e.getMessage(), e);
return WrapMapper.error(e.getMessage());
} catch (Exception e) {
getLog().error("{}更新异常: {}", getOperationName(), e.getMessage(), e);
return WrapMapper.error(getOperationName() + "更新失败");
}
}
/**
* 删除对象的通用方法
*
* @param id 对象ID
* @return 操作结果包装对象
*/
default public Wrapper<Void> delete(String id) {
try {
getService().delete(id);
return WrapMapper.ok();
} catch (BusinessException e) {
getLog().error("{}删除失败: {}", getOperationName(), e.getMessage(), e);
return WrapMapper.error(e.getMessage());
} catch (Exception e) {
getLog().error("{}删除异常: {}", getOperationName(), e.getMessage(), e);
return WrapMapper.error(getOperationName() + "删除失败");
}
}
/**
* 获取对象详情的通用方法
*
* @param id 对象ID
* @return 操作结果包装对象
*/
default public Wrapper<VO> detail(String id) {
try {
VO result = (VO) getService().detail(id);
return WrapMapper.ok(result);
} catch (BusinessException e) {
getLog().error("获取{}详情失败: {}", getOperationName(), e.getMessage(), e);
return WrapMapper.error(e.getMessage());
} catch (Exception e) {
getLog().error("获取{}详情异常: {}", getOperationName(), e.getMessage(), e);
return WrapMapper.error("获取" + getOperationName() + "详情失败");
}
}
/**
* 分页查询的通用方法
*
* @param queryDTO 查询数据传输对象
* @return 操作结果包装对象
*/
default public Wrapper<SearchResult<VO>> pageList(QueryDTO queryDTO) {
try {
SearchResult<VO> result = getService().pageList(queryDTO);
return WrapMapper.ok(result);
} catch (Exception e) {
getLog().error("查询{}列表异常: {}", getOperationName(), e.getMessage(), e);
return WrapMapper.error("查询" + getOperationName() + "列表失败");
}
}
/**
* 获取所有选项的通用方法
*
* @param queryDTO 查询数据传输对象
* @return 操作结果包装对象
*/
default public Wrapper<List<VO>> optionsList(QueryDTO queryDTO) {
try {
List<VO> result = getService().option(queryDTO);
return WrapMapper.ok(result);
} catch (Exception e) {
getLog().error("获取所有{}异常: {}", getOperationName(), e.getMessage(), e);
return WrapMapper.error("获取所有" + getOperationName() + "失败");
}
}
/**
* 导入JSONL数据的通用方法
*
* @param file JSONL文件
* @return 操作结果包装对象
*/
default public Map<String, String> importJSONLData(MultipartFile file) {
Map<String, String> result = new HashMap<>();
try {
// 读取文件内容
String content = new String(file.getBytes(), StandardCharsets.UTF_8);
// 调用服务层导入数据
result.putAll(getService().importJSONLData(content));
} catch (Exception e) {
result.put("error", "导入失败");
}
return result;
}
/**
* 导出JSONL数据的通用方法
*
* @param ids 数据主键ID
* @return 操作结果包装对象
*/
default Map<String, String> exportJSONLData(HttpServletResponse response, List<String> ids) {
// 调用服务层导入数据
getService().exportJSONLData(response, ids);
return null;
}
/**
* 从DTO中获取ID
* 默认实现子类可以重写此方法以适应不同的DTO结构
*
* @param dto 数据传输对象
* @return 对象ID
*/
default public String getIdFromDto(Object dto) {
try {
// 尝试通过反射获取id属性
java.lang.reflect.Method getIdMethod = dto.getClass().getMethod("getId");
return (String) getIdMethod.invoke(dto);
} catch (Exception e) {
getLog().warn("无法从DTO中获取ID使用默认实现", e);
return null;
}
}
} }

View File

@ -6,15 +6,17 @@ import com.example.demo.common.domain.BaseEntity;
import com.example.demo.common.domain.BaseQueryDTO; import com.example.demo.common.domain.BaseQueryDTO;
import com.example.demo.common.domain.BaseVO; import com.example.demo.common.domain.BaseVO;
import com.mybatisflex.core.service.IService; import com.mybatisflex.core.service.IService;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 统一 Service 接口 * 统一 Service 接口
* 统一定义Service基础接口 * 统一定义Service基础接口
* *
* @author system * @author 岳佳君 (2025年09月25日 22:47:55)
* @version 1.0 * @version 1.0.0
*/ */
public interface BaseService<Entity extends BaseEntity, VO extends BaseVO, DTO extends BaseDTO, QueryDTO extends BaseQueryDTO> public interface BaseService<Entity extends BaseEntity, VO extends BaseVO, DTO extends BaseDTO, QueryDTO extends BaseQueryDTO>
extends IService<Entity> { extends IService<Entity> {
@ -60,9 +62,40 @@ public interface BaseService<Entity extends BaseEntity, VO extends BaseVO, DTO e
*/ */
VO detail(String id); VO detail(String id);
/**
* 导出导入盐
* @return 导出导入盐
*/
byte[] configXPort(String ts);
/**
* 导入细节用于导入 jsonl
* @param line 导入行内容
* @return 导入处理后信息
*/
Object importDetail(String line);
/**
* 导出详情用于生成 jsonl
* @param id ID
* @return 导出处理后信息
*/
Object exportDetail(String id);
/** /**
* 刷新缓存 * 刷新缓存
*/ */
void refreshCache(); void refreshCache();
/**
* 导入JSONL数据
*/
Map<String, String> importJSONLData(String content);
/**
* 导出JSONL数据
* @param ids ID列表可以导出多条数据
*/
void exportJSONLData(HttpServletResponse response, List<String> ids);
} }

View File

@ -2,21 +2,29 @@ package com.example.demo.common.typography;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.zhxu.bs.BeanSearcher; import cn.zhxu.bs.BeanSearcher;
import cn.zhxu.bs.SearchResult; import cn.zhxu.bs.SearchResult;
import cn.zhxu.bs.operator.Contain; import cn.zhxu.bs.operator.Contain;
import cn.zhxu.bs.util.MapUtils; import cn.zhxu.bs.util.MapUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.example.demo.common.constant.GlobalConstants; import com.example.demo.common.constant.GlobalConstants;
import com.example.demo.common.domain.BaseDTO; import com.example.demo.common.domain.*;
import com.example.demo.common.domain.BaseEntity; import com.example.demo.common.exception.BusinessException;
import com.example.demo.common.domain.BaseQueryDTO;
import com.example.demo.common.domain.BaseVO;
import com.fhs.trans.service.impl.TransService; import com.fhs.trans.service.impl.TransService;
import com.mybatisflex.core.BaseMapper; import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.spring.service.impl.ServiceImpl; import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy; import jakarta.annotation.PreDestroy;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
@ -24,9 +32,20 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.List; import java.io.IOException;
import java.util.Map; import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.*;
/**
* 统一 Service 实现类
* 提供Service基础功能的通用实现
*
* @author 岳佳君 (2025年9月25日 22:55:54)
* @version 1.0.0
*/
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
public abstract class BaseServiceImpl< public abstract class BaseServiceImpl<
@ -50,6 +69,9 @@ public abstract class BaseServiceImpl<
/** 实际业务实现VO类 */ /** 实际业务实现VO类 */
private final Class<VO> clazzVO; private final Class<VO> clazzVO;
/** 实际业务实现Entity类 */
private final Class<Entity> clazzEntity;
/** 提供Select服务 */ /** 提供Select服务 */
private final BeanSearcher beanSearcher; private final BeanSearcher beanSearcher;
@ -61,11 +83,13 @@ public abstract class BaseServiceImpl<
public VO create(DTO dto) { public VO create(DTO dto) {
Entity entity = createEntity(); Entity entity = createEntity();
BeanUtil.copyProperties(dto, entity); BeanUtil.copyProperties(dto, entity);
// 新增数据 // 强制新增将ID置为空
entity.setId(null);
// 新增数据时间戳由监听器自动设置
save(entity); save(entity);
// 仅返回数据ID // 仅返回数据ID
@SuppressWarnings("all") @SuppressWarnings("all")
VO resultVO = (VO) VO.builder().id(entity.getId()).build(); VO resultVO = (VO) createVO().setId(entity.getId());
// 其他处理... // 其他处理...
return resultVO; return resultVO;
} }
@ -82,7 +106,7 @@ public abstract class BaseServiceImpl<
public Boolean update(DTO dto) { public Boolean update(DTO dto) {
Entity entity = createEntity(); Entity entity = createEntity();
BeanUtil.copyProperties(dto, entity); BeanUtil.copyProperties(dto, entity);
// 更新数据 // 更新数据时间戳由监听器自动设置
return updateById(entity); return updateById(entity);
} }
@ -96,7 +120,7 @@ public abstract class BaseServiceImpl<
// 模糊查询 // 模糊查询
.field(VO::getName, dto.getFuzzy()).op(Contain.class) .field(VO::getName, dto.getFuzzy()).op(Contain.class)
// 未删除数据 // 未删除数据
.field(VO::getIsDelete, GlobalConstants.N) .field(VO::getIsDeleted, GlobalConstants.N)
// 分页排序默认强制按照更新时间倒序单词正序 // 分页排序默认强制按照更新时间倒序单词正序
.orderBy(VO::getUpdatedTime).desc() .orderBy(VO::getUpdatedTime).desc()
.orderBy(VO::getName).asc() .orderBy(VO::getName).asc()
@ -114,7 +138,7 @@ public abstract class BaseServiceImpl<
} }
@Override @Override
public List option(QueryDTO dto) { public List<VO> option(QueryDTO dto) {
Map<String, Object> paramMap = MapUtils.builder() Map<String, Object> paramMap = MapUtils.builder()
.onlySelect( .onlySelect(
VO::getId, VO::getId,
@ -124,7 +148,7 @@ public abstract class BaseServiceImpl<
// 下拉框允许模糊筛选 // 下拉框允许模糊筛选
.field(VO::getName, dto.getFuzzy()).op(Contain.class) .field(VO::getName, dto.getFuzzy()).op(Contain.class)
// 下拉框只能查询未删除的数据 // 下拉框只能查询未删除的数据
.field(VO::getIsDelete, GlobalConstants.N) .field(VO::getIsDeleted, GlobalConstants.N)
// 下拉框强制使用单词正序时间倒序 // 下拉框强制使用单词正序时间倒序
.orderBy(VO::getName).asc() .orderBy(VO::getName).asc()
.orderBy(VO::getCreatedTime).desc() .orderBy(VO::getCreatedTime).desc()
@ -142,7 +166,7 @@ public abstract class BaseServiceImpl<
public VO detail(String id) { public VO detail(String id) {
Map<String, Object> paramMap = MapUtils.builder() Map<String, Object> paramMap = MapUtils.builder()
.field(VO::getId, id) .field(VO::getId, id)
.field(VO::getIsDelete, GlobalConstants.N) .field(VO::getIsDeleted, GlobalConstants.N)
.build(); .build();
VO wordVO = beanSearcher.searchFirst(this.clazzVO, paramMap); VO wordVO = beanSearcher.searchFirst(this.clazzVO, paramMap);
@ -153,12 +177,187 @@ public abstract class BaseServiceImpl<
return wordVO; return wordVO;
} }
@Override
public byte[] configXPort(String ts) {
String fixed = "国密";
return ensureKeyLength(fixed + ts, 16);
}
@Override
public Object importDetail(String line) {
log.warn("导入细节(暂无实现)");
JSONObject jsonObject = JSON.parseObject(line);
jsonObject.get("ts");
jsonObject.get("");
Entity entity = JSON.parseObject(line, clazzEntity);
Map<String, String> result = new HashMap<>();
// 默认导入失败
result.put("state", "error");
if(ObjectUtil.isNotEmpty(detail(entity.getId()))) {
result.put("id", entity.getId());
if(StrUtil.isNotBlank(entity.getName())) {
result.put("name", entity.getName());
}
return result;
}
// TODO 解密校验完整性
// 设置默认值
if (entity.getIsDeleted() == null) {
entity.setIsDeleted(Integer.valueOf(GlobalConstants.N));
}
// 保存到数据库
boolean flag = save(entity);
if (flag) {
result.put("state", "success");
}
return null;
}
@Override
public Object exportDetail(String id) {
log.warn("导出细节(暂无实现)");
return null;
}
@Override @Override
public void refreshCache() { public void refreshCache() {
// ignore // ignore
log.warn("刷新缓存(暂无实现)"); log.warn("刷新缓存(暂无实现)");
} }
@Override
public Map<String, String> importJSONLData(String content) {
Map<String, String> result = new HashMap<>();
int successCount = 0;
int failCount = 0;
List<String> errors = new ArrayList<>();
try {
// 按行分割JSONL数据
String[] lines = content.split("\n");
for (int i = 0; i < lines.length; i++) {
String line = lines[i].trim();
if (line.isEmpty()) continue;
try {
// 解析每一行JSON为Entity对象
// 使用try-catch块忽略无法转化的数据继续处理下一行
importDetail(line);
successCount++;
} catch (Exception e) {
// 记录失败信息但继续处理下一行数据
failCount++;
errors.add("" + (i + 1) + "行导入失败: " + e.getMessage());
log.warn("忽略无法解析的JSON数据行[{}]: {}", i + 1, line);
// 继续处理下一行不抛出异常中断整体流程
continue;
}
}
result.put("successCount", String.valueOf(successCount));
result.put("failCount", String.valueOf(failCount));
result.put("errors", String.join("\n", errors));
result.put("message", "导入完成,成功 " + successCount + " 条,失败 " + failCount + "");
} catch (Exception e) {
result.put("error", "解析JSONL数据失败: " + e.getMessage());
result.put("successCount", "0");
result.put("failCount", "0");
result.put("message", "导入失败");
}
return result;
}
@Override
public void exportJSONLData(HttpServletResponse response, List<String> ids) {
try {
if (ids == null || ids.isEmpty()) {
throw new BusinessException("导出ID列表不能为空");
}
String ts = String.valueOf(System.currentTimeMillis());
byte[] keyBytes = configXPort(ts);
SymmetricCrypto sm4 = SmUtil.sm4(keyBytes);
// 验证并获取所有要导出的数据
List<Object> list = new ArrayList<>();
for (String id : ids) {
try {
// 使用detail方法验证ID是否存在并获取数据
Object obj = exportDetail(id);
if (obj == null) {
throw new BusinessException("不存在: " + id);
}
String content = JSON.toJSONString(obj);
// 加密
sm4.encryptHex(content);
// 统一结构体
BaseXPortData xPortData = BaseXPortData.builder()
.id(id)
.ts(ts)
.data(content)
.build();
// 添加到导出列表
list.add(xPortData);
} catch (Exception e) {
// ignore
}
}
// 准备文件流和文件名列表用于压缩
List<String> fileNameUniqueList = new ArrayList<>();
List<InputStream> inputStreams = new ArrayList<>();
// 创建一个JSONL文件包含所有模板数据每行一个JSON对象
StringBuilder jsonlContent = new StringBuilder();
for (Object object : list) {
String jsonContent = JSON.toJSONString(object);
jsonlContent.append(jsonContent).append("\n");
}
InputStream is = IoUtil.toStream(jsonlContent.toString(), StandardCharsets.UTF_8);
fileNameUniqueList.add(
String.format("%s-%s-%s.jsonl",
// getOperationName(),
"数据",
DateUtil.format(new Date(), "yyyyMMdd"),
IdUtil.simpleUUID()
));
inputStreams.add(is);
// 转换为数组
String[] fileNamesArr = fileNameUniqueList.toArray(new String[0]);
InputStream[] inputStreamsArr = inputStreams.toArray(new InputStream[0]);
// 使用ZipUtil进行压缩下载
try {
ZipUtil.zip(response.getOutputStream(), fileNamesArr, inputStreamsArr);
} catch (IOException e) {
throw new BusinessException("压缩下载失败: " + e.getMessage());
} finally {
// 关闭所有输入流
for (InputStream inputStream : inputStreams) {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
// 忽略关闭流的异常
}
}
}
} catch (BusinessException e) {
// 直接抛出业务异常保留原始错误信息
throw e;
} catch (Exception e) {
throw new BusinessException("导出JSONL数据失败: " + e.getMessage());
}
}
@PostConstruct @PostConstruct
public void init() { public void init() {
// ignore // ignore
@ -185,24 +384,103 @@ public abstract class BaseServiceImpl<
*/ */
@SuppressWarnings("all") @SuppressWarnings("all")
protected Entity createEntity() { protected Entity createEntity() {
return (Entity) Entity.builder().build(); try {
// 使用反射获取具体的实体类并创建实例
Class<?> entityClass = getEntityClass();
return (Entity) entityClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException("创建实体实例失败", e);
}
} }
/** /**
* 实例化 entity * 实例化 VO
* @return 获取新实例化 entity * @return 获取新实例化 VO
*/ */
@SuppressWarnings("all") @SuppressWarnings("all")
protected VO createVO() { protected VO createVO() {
return (VO) VO.builder().build(); try {
// 使用反射获取具体的VO类并创建实例
Class<?> voClass = getVOClass();
return (VO) voClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException("创建VO实例失败", e);
}
} }
/** /**
* 实例化 entity * 实例化 DTO
* @return 获取新实例化 entity * @return 获取新实例化 DTO
*/ */
@SuppressWarnings("all") @SuppressWarnings("all")
protected DTO createDTO() { protected DTO createDTO() {
return (DTO) DTO.builder().build(); try {
// 使用反射获取具体的DTO类并创建实例
Class<?> dtoClass = getDTOClass();
return (DTO) dtoClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException("创建DTO实例失败", e);
} }
} }
/**
* 获取实体类的Class对象
* @return 实体类的Class对象
*/
@SuppressWarnings("unchecked")
private Class<Entity> getEntityClass() {
// 通过获取泛型参数类型来确定具体的实体类
Type superClass = getClass().getGenericSuperclass();
ParameterizedType parameterizedType = (ParameterizedType) superClass;
return (Class<Entity>) parameterizedType.getActualTypeArguments()[0];
}
/**
* 获取VO类的Class对象
* @return VO类的Class对象
*/
@SuppressWarnings("unchecked")
private Class<VO> getVOClass() {
// 通过获取泛型参数类型来确定具体的VO类
Type superClass = getClass().getGenericSuperclass();
ParameterizedType parameterizedType = (ParameterizedType) superClass;
return (Class<VO>) parameterizedType.getActualTypeArguments()[1];
}
/**
* 获取DTO类的Class对象
* @return DTO类的Class对象
*/
@SuppressWarnings("unchecked")
private Class<DTO> getDTOClass() {
// 通过获取泛型参数类型来确定具体的DTO类
Type superClass = getClass().getGenericSuperclass();
ParameterizedType parameterizedType = (ParameterizedType) superClass;
return (Class<DTO>) parameterizedType.getActualTypeArguments()[2];
}
/**
* 确保密钥字节数组为指定长度
* @param key 原始密钥字符串
* @param length 所需长度
* @return 调整后的密钥字节数组
*/
private static byte[] ensureKeyLength(String key, int length) {
byte[] keyBytes = key.getBytes(java.nio.charset.StandardCharsets.UTF_8);
if (keyBytes.length == length) {
return keyBytes;
} else if (keyBytes.length > length) {
// 如果太长则截取
byte[] result = new byte[length];
System.arraycopy(keyBytes, 0, result, 0, length);
return result;
} else {
// 如果太短则填充0或者您可以选择其他填充方式
byte[] result = new byte[length];
System.arraycopy(keyBytes, 0, result, 0, keyBytes.length);
// 剩余部分默认为0
return result;
}
}
}

View File

@ -0,0 +1,426 @@
package com.example.demo.common.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 坐标转换工具类支持大地坐标与空间直角坐标的正算和反算
* 支持多种椭球参数WGS84CGCS2000等
*
* <p>大地坐标Geodetic Coordinate由纬度B经度L和大地高H组成
* <p>空间直角坐标Cartesian Coordinate由XYZ三个分量组成
*
* @author 岳佳君 (2025年9月29日 15:02:13)
* @version 1.0.0
*/
public class CoordinateConverterUtil {
/**
* 椭球参数接口定义了椭球的基本参数
*/
public interface Ellipsoid {
/**
* 获取椭球长半轴赤道半径单位
* @return 长半轴值
*/
double getSemiMajorAxis();
/**
* 获取椭球短半轴极半径单位
* @return 短半轴值
*/
double getSemiMinorAxis();
/**
* 获取第一偏心率平方
* @return 第一偏心率平方值
*/
double getFirstEccentricitySquared();
/**
* 获取第二偏心率平方
* @return 第二偏心率平方值
*/
double getSecondEccentricitySquared();
}
/**
* WGS84椭球参数实现
* <p>WGS84是GPS系统使用的椭球参数
*/
public static class WGS84Ellipsoid implements Ellipsoid {
// 长半轴单位
private static final double SEMI_MAJOR_AXIS = 6378137.0;
// 短半轴单位
private static final double SEMI_MINOR_AXIS = 6356752.314245179;
// 第一偏心率平方
private static final double FIRST_ECCENTRICITY_SQUARED = 0.0066943799901413165;
// 第二偏心率平方
private static final double SECOND_ECCENTRICITY_SQUARED = 0.006739496742276435;
@Override
public double getSemiMajorAxis() {
return SEMI_MAJOR_AXIS;
}
@Override
public double getSemiMinorAxis() {
return SEMI_MINOR_AXIS;
}
@Override
public double getFirstEccentricitySquared() {
return FIRST_ECCENTRICITY_SQUARED;
}
@Override
public double getSecondEccentricitySquared() {
return SECOND_ECCENTRICITY_SQUARED;
}
}
/**
* CGCS2000椭球参数实现
* <p>CGCS2000是中国国家大地坐标系使用的椭球参数
*/
public static class CGCS2000Ellipsoid implements Ellipsoid {
// 长半轴单位
private static final double SEMI_MAJOR_AXIS = 6378137.0;
// 短半轴单位
private static final double SEMI_MINOR_AXIS = 6356752.314140356;
// 第一偏心率平方
private static final double FIRST_ECCENTRICITY_SQUARED = 0.006694380022903416;
// 第二偏心率平方
private static final double SECOND_ECCENTRICITY_SQUARED = 0.006739496775481663;
@Override
public double getSemiMajorAxis() {
return SEMI_MAJOR_AXIS;
}
@Override
public double getSemiMinorAxis() {
return SEMI_MINOR_AXIS;
}
@Override
public double getFirstEccentricitySquared() {
return FIRST_ECCENTRICITY_SQUARED;
}
@Override
public double getSecondEccentricitySquared() {
return SECOND_ECCENTRICITY_SQUARED;
}
}
/**
* 大地坐标模型类包含纬度经度和大地高
*/
public static class GeodeticCoordinate {
// 纬度单位弧度北半球为正南半球为负
private final double latitude;
// 经度单位弧度东经为正西经为负
private final double longitude;
// 大地高单位
private final double height;
/**
* 构造函数
* @param latitude 纬度弧度
* @param longitude 经度弧度
* @param height 大地高
*/
public GeodeticCoordinate(double latitude, double longitude, double height) {
this.latitude = latitude;
this.longitude = longitude;
this.height = height;
}
/**
* 获取纬度弧度
* @return 纬度值
*/
public double getLatitude() {
return latitude;
}
/**
* 获取经度弧度
* @return 经度值
*/
public double getLongitude() {
return longitude;
}
/**
* 获取大地高
* @return 大地高值
*/
public double getHeight() {
return height;
}
@Override
public String toString() {
// 转换为度格式显示
return String.format("GeodeticCoordinate [纬度=%.6f°, 经度=%.6f°, 大地高=%.2fm]",
Math.toDegrees(latitude), Math.toDegrees(longitude), height);
}
}
/**
* 空间直角坐标模型类包含XYZ三个分量
*/
public static class CartesianCoordinate {
// X坐标单位
private final double x;
// Y坐标单位
private final double y;
// Z坐标单位
private final double z;
/**
* 构造函数
* @param x X坐标
* @param y Y坐标
* @param z Z坐标
*/
public CartesianCoordinate(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
/**
* 获取X坐标
* @return X坐标值
*/
public double getX() {
return x;
}
/**
* 获取Y坐标
* @return Y坐标值
*/
public double getY() {
return y;
}
/**
* 获取Z坐标
* @return Z坐标值
*/
public double getZ() {
return z;
}
@Override
public String toString() {
return String.format("CartesianCoordinate [X=%.2fm, Y=%.2fm, Z=%.2fm]", x, y, z);
}
}
// 默认椭球参数为WGS84
private static final Ellipsoid DEFAULT_ELLIPSOID = new WGS84Ellipsoid();
// 迭代计算精度单位弧度约等于0.00000057度
private static final double ITERATION_PRECISION = 1e-10;
// 最大迭代次数
private static final int MAX_ITERATIONS = 10;
/**
* 大地坐标正算将大地坐标转换为空间直角坐标
* 使用默认椭球参数WGS84
*
* @param geodetic 大地坐标纬度经度单位为弧度
* @return 空间直角坐标
*/
public static CartesianCoordinate geodeticToCartesian(GeodeticCoordinate geodetic) {
return geodeticToCartesian(geodetic, DEFAULT_ELLIPSOID);
}
/**
* 大地坐标正算将大地坐标转换为空间直角坐标
*
* @param geodetic 大地坐标纬度经度单位为弧度
* @param ellipsoid 椭球参数
* @return 空间直角坐标
*/
public static CartesianCoordinate geodeticToCartesian(GeodeticCoordinate geodetic, Ellipsoid ellipsoid) {
// 验证输入参数
if (geodetic == null) {
throw new IllegalArgumentException("大地坐标不能为空");
}
if (ellipsoid == null) {
throw new IllegalArgumentException("椭球参数不能为空");
}
double B = geodetic.getLatitude(); // 纬度弧度
double L = geodetic.getLongitude(); // 经度弧度
double H = geodetic.getHeight(); // 大地高
double a = ellipsoid.getSemiMajorAxis();
double e2 = ellipsoid.getFirstEccentricitySquared();
// 计算卯酉圈曲率半径N
double sinB = Math.sin(B);
double cosB = Math.cos(B);
double cosL = Math.cos(L);
double sinL = Math.sin(L);
double N = a / Math.sqrt(1 - e2 * sinB * sinB);
// 计算空间直角坐标
double X = (N + H) * cosB * cosL;
double Y = (N + H) * cosB * sinL;
double Z = (N * (1 - e2) + H) * sinB;
// 保留6位小数精度
X = round(X, 6);
Y = round(Y, 6);
Z = round(Z, 6);
return new CartesianCoordinate(X, Y, Z);
}
/**
* 大地坐标反算将空间直角坐标转换为大地坐标
* 使用默认椭球参数WGS84
*
* @param cartesian 空间直角坐标
* @return 大地坐标纬度经度单位为弧度
*/
public static GeodeticCoordinate cartesianToGeodetic(CartesianCoordinate cartesian) {
return cartesianToGeodetic(cartesian, DEFAULT_ELLIPSOID);
}
/**
* 大地坐标反算将空间直角坐标转换为大地坐标
*
* @param cartesian 空间直角坐标
* @param ellipsoid 椭球参数
* @return 大地坐标纬度经度单位为弧度
*/
public static GeodeticCoordinate cartesianToGeodetic(CartesianCoordinate cartesian, Ellipsoid ellipsoid) {
// 验证输入参数
if (cartesian == null) {
throw new IllegalArgumentException("空间直角坐标不能为空");
}
if (ellipsoid == null) {
throw new IllegalArgumentException("椭球参数不能为空");
}
double X = cartesian.getX();
double Y = cartesian.getY();
double Z = cartesian.getZ();
double a = ellipsoid.getSemiMajorAxis();
double b = ellipsoid.getSemiMinorAxis();
double e2 = ellipsoid.getFirstEccentricitySquared();
double ePrime2 = ellipsoid.getSecondEccentricitySquared();
// 计算经度L
double L;
if (X == 0 && Y == 0) {
L = 0; // 位于极点经度无意义设为0
} else {
L = Math.atan2(Y, X); // 计算经度弧度
}
// 计算点到地轴的距离r
double r = Math.sqrt(X * X + Y * Y);
// 特殊情况处理如果r为0说明在极点
if (r == 0) {
double B = (Z > 0) ? Math.PI / 2 : -Math.PI / 2; // 北极或南极
double H = Math.abs(Z) - b; // 大地高
return new GeodeticCoordinate(B, L, H);
}
// 迭代计算纬度B
double B = Math.atan2(Z, r * (1 - e2)); // 初始值
double previousB;
int iterations = 0;
do {
previousB = B;
double sinB = Math.sin(B);
// 计算卯酉圈曲率半径N
double N = a / Math.sqrt(1 - e2 * sinB * sinB);
// 迭代计算新的纬度
B = Math.atan2(Z + N * e2 * sinB, r);
iterations++;
} while (Math.abs(B - previousB) > ITERATION_PRECISION && iterations < MAX_ITERATIONS);
// 计算大地高H
double sinB = Math.sin(B);
double cosB = Math.cos(B);
double N = a / Math.sqrt(1 - e2 * sinB * sinB);
double H = (r / cosB) - N;
// 保留8位小数精度
B = round(B, 8);
L = round(L, 8);
H = round(H, 6);
return new GeodeticCoordinate(B, L, H);
}
/**
* 角度转换度分秒转弧度
*
* @param degrees
* @param minutes
* @param seconds
* @return 转换后的弧度值
*/
public static double dmsToRadians(int degrees, int minutes, double seconds) {
if (degrees < 0 || minutes < 0 || minutes >= 60 || seconds < 0 || seconds >= 60) {
throw new IllegalArgumentException("无效的度分秒值");
}
double decimalDegrees = degrees + minutes / 60.0 + seconds / 3600.0;
return Math.toRadians(decimalDegrees);
}
/**
* 角度转换弧度转度分秒表示的字符串
*
* @param radians 弧度值
* @return 度分秒格式的字符串例如30°15'22.5"
*/
public static String radiansToDmsString(double radians) {
double degrees = Math.toDegrees(radians);
int deg = (int) Math.floor(Math.abs(degrees));
double minutes = (Math.abs(degrees) - deg) * 60;
int min = (int) Math.floor(minutes);
double sec = (minutes - min) * 60;
// 保留两位小数
sec = round(sec, 2);
// 处理符号
String sign = degrees >= 0 ? "" : "-";
return String.format("%s%d°%d'%f\"", sign, deg, min, sec);
}
/**
* 四舍五入保留指定小数位数
*
* @param value 要处理的数值
* @param decimalPlaces 保留的小数位数
* @return 处理后的数值
*/
private static double round(double value, int decimalPlaces) {
if (decimalPlaces < 0) {
throw new IllegalArgumentException("小数位数不能为负数");
}
BigDecimal bd = new BigDecimal(Double.toString(value));
bd = bd.setScale(decimalPlaces, RoundingMode.HALF_UP);
return bd.doubleValue();
}
}

View File

@ -17,8 +17,8 @@ import java.util.concurrent.TimeUnit;
* 文件操作工具类 * 文件操作工具类
* 提供文件读写复制删除等通用功能 * 提供文件读写复制删除等通用功能
* *
* @author system * @author 岳佳君 (2025年09月26日 13:48:12)
* @version 1.0 * @version 1.0.0
*/ */
public class FileUtil { public class FileUtil {

View File

@ -0,0 +1,124 @@
package com.example.demo.common.utils;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class WebHookUtil {
@SneakyThrows
public static void main(String[] args) {
demo01();
}
@SneakyThrows
private static void demo01() {
webHook(
"key",
"通知",
"",
"""
任务执行\r
核心思想化整为零动态调整\r
将复杂的项目目标分解为一个个可执行可跟踪可验收的小任务并通过持续的沟通和调整来确保方向正确\r
本消息由 虚兵001 提供""");
webHook(
"key",
"最新通知",
"",
"""
AI资讯\r
- 多模态模型社区全新升级LiblibAI 2.0正式上线\r
- 快手推出AI原生IDE工具CodeFlicker对标Cursor\r
- 蚂蚁百灵正式发布Ling 2.0系列的首款旗舰非思考模型Ling-1T\r
本消息由 虚兵002 提供""");
String secret = "secret";
webHook(
"key",
"通知",
secret,
"北京市朝阳区今天实况:" +
"\n 17度 晴湿度62%北风1级。" +
"\n 白天22度,晴。 " +
"\n 夜间11度温度适中。" +
"\n注本消息由 虚兵003 提供");
webHook(
"key",
"",
secret,
"今天中国的黄金价格是 每克 CN¥921.28 24k 金子, 每克 CN¥844.51 " +
"\n注本消息由 虚兵003 提供");
}
public static void webHook(String url, String prefix, String secret, String message) throws NoSuchAlgorithmException, InvalidKeyException {
String baseURL = "https://open.feishu.cn/open-apis/bot/v2/hook/";
int timestamp = (int) (System.currentTimeMillis() / 1000);
String sign = GenSign(secret, timestamp);
String fullMessage = StrUtil.isBlank(prefix) ? message : String.format("%s\n %s", prefix, message);
Map<String, Object> requestData = createMessage(sign, timestamp, fullMessage);
String fullURL = String.format("%s%s", baseURL, url);
// 直接发送map报错参数错误
// String responseData = HttpUtil.post(fullURL, requestData);
String responseData = HttpUtil.post(fullURL, JSON.toJSONString(requestData));
log.info("responseData: {}", responseData);
log.info("URL: {}", fullURL);
log.info("requestData: {}", JSON.toJSONString(requestData));
}
public static String createWebHookData(String secret, String message) throws NoSuchAlgorithmException, InvalidKeyException {
int timestamp = (int) (System.currentTimeMillis() / 1000);
String sign = GenSign(secret, timestamp);
Map<String, Object> requestData = createMessage(sign, timestamp, message);
@SuppressWarnings("all")
String requestJSONString = JSON.toJSONString(requestData);
return requestJSONString;
}
private static Map<String, Object> createMessage(String secret, int timestamp, String message) throws NoSuchAlgorithmException, InvalidKeyException {
Map<String, Object> map = new HashMap<>();
if(StrUtil.isNotBlank(secret)) {
map.put("timestamp", timestamp);
map.put("sign", secret);
}
map.put("msg_type", "text");
Map<String, Object> content = new HashMap<>();
content.put("text", message);
map.put("content", content);
return map;
}
public static String createWebHook(String message) {
return null;
}
private static String GenSign(String secret, int timestamp) throws NoSuchAlgorithmException, InvalidKeyException {
if(StrUtil.isBlank(secret)) {
return null;
}
//把timestamp+"\n"+密钥当做签名字符串
String stringToSign = timestamp + "\n" + secret;
//使用HmacSHA256算法计算签名
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] signData = mac.doFinal(new byte[]{});
return new String(Base64.encodeBase64(signData));
}
}

View File

@ -15,8 +15,8 @@ import java.util.*;
* XML解析工具类 * XML解析工具类
* 提供XML文件解析和转换为TXT文件的核心功能 * 提供XML文件解析和转换为TXT文件的核心功能
* *
* @author system * @author 岳佳君 (2025年09月24日 23:09:02)
* @version 1.0 * @version 1.0.0
*/ */
public class XmlParserUtil { public class XmlParserUtil {

View File

@ -4,8 +4,8 @@ package com.example.demo.common.wrapper;
* 统一响应包装工具类 * 统一响应包装工具类
* 提供静态方法创建Wrapper实例 * 提供静态方法创建Wrapper实例
* *
* @author system * @author 岳佳君 (2025年09月25日 23:42:44)
* @version 1.0 * @version 1.0.0
*/ */
public class WrapMapper { public class WrapMapper {
@ -14,7 +14,7 @@ public class WrapMapper {
* *
* @return 响应结果 * @return 响应结果
*/ */
public static Wrapper<Object> ok() { public static <ResponseData> Wrapper<ResponseData> ok() {
return ok(null, "操作成功"); return ok(null, "操作成功");
} }
@ -34,7 +34,7 @@ public class WrapMapper {
* @param data 响应数据 * @param data 响应数据
* @return 响应结果 * @return 响应结果
*/ */
public static <T> Wrapper<T> ok(T data) { public static <ResponseData> Wrapper<ResponseData> ok(ResponseData data) {
return ok(data, "操作成功"); return ok(data, "操作成功");
} }
@ -45,8 +45,8 @@ public class WrapMapper {
* @param message 响应消息 * @param message 响应消息
* @return 响应结果 * @return 响应结果
*/ */
public static <T> Wrapper<T> ok(T data, String message) { public static <ResponseData> Wrapper<ResponseData> ok(ResponseData data, String message) {
Wrapper<T> result = new Wrapper<>(); Wrapper<ResponseData> result = new Wrapper<>();
result.setCode("SUCCESS"); result.setCode("SUCCESS");
result.setMessage(message); result.setMessage(message);
result.setData(data); result.setData(data);
@ -54,12 +54,31 @@ public class WrapMapper {
return result; return result;
} }
/**
* 错误响应默认消息
*
* @return 响应结果
*/
public static <ResponseData> Wrapper<ResponseData> error() {
return fail("ERROR", "操作错误");
}
/**
* 错误响应带消息
*
* @param message 响应消息
* @return 响应结果
*/
public static <ResponseData> Wrapper<ResponseData> error(String message) {
return fail("ERROR", message);
}
/** /**
* 失败响应默认消息 * 失败响应默认消息
* *
* @return 响应结果 * @return 响应结果
*/ */
public static <T> Wrapper<T> fail() { public static <ResponseData> Wrapper<ResponseData> fail() {
return fail("FAIL", "操作失败"); return fail("FAIL", "操作失败");
} }
@ -69,7 +88,7 @@ public class WrapMapper {
* @param message 响应消息 * @param message 响应消息
* @return 响应结果 * @return 响应结果
*/ */
public static <T> Wrapper<T> fail(String message) { public static <ResponseData> Wrapper<ResponseData> fail(String message) {
return fail("FAIL", message); return fail("FAIL", message);
} }
@ -80,8 +99,8 @@ public class WrapMapper {
* @param message 响应消息 * @param message 响应消息
* @return 响应结果 * @return 响应结果
*/ */
public static <T> Wrapper<T> fail(String code, String message) { public static <ResponseData> Wrapper<ResponseData> fail(String code, String message) {
Wrapper<T> result = new Wrapper<>(); Wrapper<ResponseData> result = new Wrapper<>();
result.setCode(code); result.setCode(code);
result.setMessage(message); result.setMessage(message);
result.setTimestamp(System.currentTimeMillis()); result.setTimestamp(System.currentTimeMillis());

View File

@ -12,8 +12,8 @@ import java.io.Serializable;
* 用于封装所有RESTful API的响应数据 * 用于封装所有RESTful API的响应数据
* *
* @param <T> 响应数据类型 * @param <T> 响应数据类型
* @author system * @author 岳佳君 (2025年09月25日 23:42:44)
* @version 1.0 * @version 1.0.0
*/ */
@Data @Data
@NoArgsConstructor @NoArgsConstructor

View File

@ -1,110 +0,0 @@
package com.example.demo.draft.demo043.core;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
/**
* 模板文件工具类
* 负责从文件系统或类路径加载模板文件
*/
@Slf4j
public class TemplateFileLoader {
private static final String DEFAULT_TEMPLATE_DIR = "templates/";
private static final String CLASS_PATH_PREFIX = "classpath:";
private static final String FILE_PATH_PREFIX = "file:";
// 模板缓存
private static final Map<String, String> TEMPLATE_CACHE = new HashMap<>();
/**
* 从类路径加载模板文件
*/
public static String loadTemplateFromClasspath(String templatePath) throws IOException {
String cacheKey = CLASS_PATH_PREFIX + templatePath;
if (TEMPLATE_CACHE.containsKey(cacheKey)) {
return TEMPLATE_CACHE.get(cacheKey);
}
try {
// 从类路径加载
String fullPath = templatePath.startsWith("/") ? templatePath : "/" + templatePath;
java.io.InputStream inputStream = TemplateFileLoader.class.getResourceAsStream(fullPath);
if (inputStream == null) {
throw new IOException("模板文件未找到: " + templatePath);
}
String content = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
TEMPLATE_CACHE.put(cacheKey, content);
log.info("从类路径加载模板: {}", templatePath);
return content;
} catch (IOException e) {
log.error("从类路径加载模板失败: {}", templatePath, e);
throw e;
}
}
/**
* 从文件系统加载模板文件
*/
public static String loadTemplateFromFileSystem(String filePath) throws IOException {
String cacheKey = FILE_PATH_PREFIX + filePath;
if (TEMPLATE_CACHE.containsKey(cacheKey)) {
return TEMPLATE_CACHE.get(cacheKey);
}
try {
Path path = Paths.get(filePath);
if (!Files.exists(path)) {
throw new IOException("模板文件不存在: " + filePath);
}
String content = Files.readString(path, StandardCharsets.UTF_8);
TEMPLATE_CACHE.put(cacheKey, content);
log.info("从文件系统加载模板: {}", filePath);
return content;
} catch (IOException e) {
log.error("从文件系统加载模板失败: {}", filePath, e);
throw e;
}
}
/**
* 智能加载模板自动判断路径类型
*/
public static String loadTemplate(String templatePath) throws IOException {
if (templatePath.startsWith(CLASS_PATH_PREFIX)) {
return loadTemplateFromClasspath(templatePath.substring(CLASS_PATH_PREFIX.length()));
} else if (templatePath.startsWith(FILE_PATH_PREFIX)) {
return loadTemplateFromFileSystem(templatePath.substring(FILE_PATH_PREFIX.length()));
} else {
// 默认从类路径加载
return loadTemplateFromClasspath(templatePath);
}
}
/**
* 清除模板缓存
*/
public static void clearCache() {
TEMPLATE_CACHE.clear();
log.info("模板缓存已清除");
}
/**
* 获取缓存中的模板数量
*/
public static int getCacheSize() {
return TEMPLATE_CACHE.size();
}
}

View File

@ -0,0 +1,171 @@
package com.example.demo.parser.controller;
import cn.zhxu.bs.SearchResult;
import com.example.demo.common.wrapper.WrapMapper;
import com.example.demo.common.wrapper.Wrapper;
import com.example.demo.common.exception.BusinessException;
import com.example.demo.parser.model.dto.ConditionMapDTO;
import com.example.demo.parser.model.dto.ConditionMapQueryDTO;
import com.example.demo.parser.model.vo.ConditionMapVO;
import com.example.demo.parser.service.ConditionMapService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 条件类型映射控制器
* 提供条件类型映射管理的RESTful API接口
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Slf4j
@RestController
@RequestMapping("/parser/condition-maps")
@RequiredArgsConstructor
@Tag(name = "条件类型映射管理", description = "提供条件类型映射管理的接口")
public class ConditionMapController {
private final ConditionMapService conditionMapService;
/**
* 创建条件类型映射
*
* @param conditionMap 条件类型映射数据
* @return 操作结果包装对象
*/
@PostMapping
@Operation(summary = "创建条件类型映射", description = "创建新的条件类型映射")
public Wrapper<ConditionMapVO> createConditionMap(
@Parameter(description = "条件类型映射数据", required = true)
@RequestBody ConditionMapDTO conditionMap) {
try {
ConditionMapVO result = conditionMapService.create(conditionMap);
return WrapMapper.ok(result, "条件类型映射创建成功");
} catch (BusinessException e) {
log.error("条件类型映射创建失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("条件类型映射创建异常: {}", e.getMessage(), e);
return WrapMapper.fail("条件类型映射创建失败");
}
}
/**
* 更新条件类型映射
*
* @param conditionMapId 条件类型映射ID
* @param conditionMap 条件类型映射数据
* @return 操作结果包装对象
*/
@PutMapping("/{conditionMapId}")
@Operation(summary = "更新条件类型映射", description = "更新指定的条件类型映射")
public Wrapper<ConditionMapVO> updateConditionMap(
@Parameter(description = "条件类型映射ID", required = true)
@PathVariable String conditionMapId,
@Parameter(description = "条件类型映射数据", required = true)
@RequestBody ConditionMapDTO conditionMap) {
try {
conditionMapService.update(conditionMap);
ConditionMapVO result = conditionMapService.detail(conditionMap.getId());
return WrapMapper.ok(result, "条件类型映射更新成功");
} catch (BusinessException e) {
log.error("条件类型映射更新失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("条件类型映射更新异常: {}", e.getMessage(), e);
return WrapMapper.fail("条件类型映射更新失败");
}
}
/**
* 删除条件类型映射
*
* @param conditionMapId 条件类型映射ID
* @return 操作结果包装对象
*/
@DeleteMapping("/{conditionMapId}")
@Operation(summary = "删除条件类型映射", description = "删除指定的条件类型映射")
public Wrapper<Void> deleteConditionMap(
@Parameter(description = "条件类型映射ID", required = true)
@PathVariable String conditionMapId) {
try {
conditionMapService.delete(conditionMapId);
return WrapMapper.ok(null, "条件类型映射删除成功");
} catch (BusinessException e) {
log.error("条件类型映射删除失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("条件类型映射删除异常: {}", e.getMessage(), e);
return WrapMapper.fail("条件类型映射删除失败");
}
}
/**
* 获取条件类型映射详情
*
* @param conditionMapId 条件类型映射ID
* @return 条件类型映射详情包装对象
*/
@GetMapping("/{conditionMapId}")
@Operation(summary = "获取条件类型映射详情", description = "根据ID获取条件类型映射的详细信息")
public Wrapper<ConditionMapVO> getConditionMap(
@Parameter(description = "条件类型映射ID", required = true)
@PathVariable String conditionMapId) {
try {
ConditionMapVO result = conditionMapService.detail(conditionMapId);
return WrapMapper.ok(result, "获取条件类型映射详情成功");
} catch (BusinessException e) {
log.error("获取条件类型映射详情失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("获取条件类型映射详情异常: {}", e.getMessage(), e);
return WrapMapper.fail("获取条件类型映射详情失败");
}
}
/**
* 分页查询条件类型映射列表
*
* @param queryDTO 查询封装对象
* @return 分页结果包装对象
*/
@PostMapping("/page")
@Operation(summary = "分页查询条件类型映射", description = "分页查询条件类型映射列表")
public Wrapper<SearchResult<ConditionMapVO>> pageList(
@Parameter(description = "条件类型映射QueryDTO数据", required = true)
@RequestBody ConditionMapQueryDTO queryDTO) {
try {
SearchResult<ConditionMapVO> result = conditionMapService.pageList(queryDTO);
return WrapMapper.ok(result);
} catch (Exception e) {
log.error("查询条件类型映射列表异常: {}", e.getMessage(), e);
return WrapMapper.fail("查询条件类型映射列表失败");
}
}
/**
* 获取所有条件类型映射列表
*
* @param queryDTO 查询封装对象
* @return 条件类型映射列表包装对象
*/
@PostMapping("/options")
@Operation(summary = "获取所有条件类型映射", description = "获取所有条件类型映射的列表")
public Wrapper<List<ConditionMapVO>> options(
@Parameter(description = "条件类型映射QueryDTO数据", required = true)
@RequestBody ConditionMapQueryDTO queryDTO) {
try {
List<ConditionMapVO> result = conditionMapService.option(queryDTO);
return WrapMapper.ok(result, "获取所有条件类型映射成功");
} catch (Exception e) {
log.error("获取所有条件类型映射异常: {}", e.getMessage(), e);
return WrapMapper.fail("获取所有条件类型映射失败");
}
}
}

View File

@ -0,0 +1,171 @@
package com.example.demo.parser.controller;
import cn.zhxu.bs.SearchResult;
import com.example.demo.common.wrapper.WrapMapper;
import com.example.demo.common.wrapper.Wrapper;
import com.example.demo.common.exception.BusinessException;
import com.example.demo.parser.model.dto.ConfigDocumentDTO;
import com.example.demo.parser.model.dto.ConfigDocumentQueryDTO;
import com.example.demo.parser.model.vo.ConfigDocumentVO;
import com.example.demo.parser.service.ConfigDocumentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 配置文档控制器
* 提供配置文档管理的RESTful API接口
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Slf4j
@RestController
@RequestMapping("/parser/config-documents")
@RequiredArgsConstructor
@Tag(name = "配置文档管理", description = "提供配置文档管理的接口")
public class ConfigDocumentController {
private final ConfigDocumentService configDocumentService;
/**
* 创建配置文档
*
* @param configDocument 配置文档数据
* @return 操作结果包装对象
*/
@PostMapping
@Operation(summary = "创建配置文档", description = "创建新的配置文档")
public Wrapper<ConfigDocumentVO> createConfigDocument(
@Parameter(description = "配置文档数据", required = true)
@RequestBody ConfigDocumentDTO configDocument) {
try {
ConfigDocumentVO result = configDocumentService.create(configDocument);
return WrapMapper.ok(result, "配置文档创建成功");
} catch (BusinessException e) {
log.error("配置文档创建失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("配置文档创建异常: {}", e.getMessage(), e);
return WrapMapper.fail("配置文档创建失败");
}
}
/**
* 更新配置文档
*
* @param configDocumentId 配置文档ID
* @param configDocument 配置文档数据
* @return 操作结果包装对象
*/
@PutMapping("/{configDocumentId}")
@Operation(summary = "更新配置文档", description = "更新指定的配置文档")
public Wrapper<ConfigDocumentVO> updateConfigDocument(
@Parameter(description = "配置文档ID", required = true)
@PathVariable String configDocumentId,
@Parameter(description = "配置文档数据", required = true)
@RequestBody ConfigDocumentDTO configDocument) {
try {
configDocumentService.update(configDocument);
ConfigDocumentVO result = configDocumentService.detail(configDocument.getId());
return WrapMapper.ok(result, "配置文档更新成功");
} catch (BusinessException e) {
log.error("配置文档更新失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("配置文档更新异常: {}", e.getMessage(), e);
return WrapMapper.fail("配置文档更新失败");
}
}
/**
* 删除配置文档
*
* @param configDocumentId 配置文档ID
* @return 操作结果包装对象
*/
@DeleteMapping("/{configDocumentId}")
@Operation(summary = "删除配置文档", description = "删除指定的配置文档")
public Wrapper<Void> deleteConfigDocument(
@Parameter(description = "配置文档ID", required = true)
@PathVariable String configDocumentId) {
try {
configDocumentService.delete(configDocumentId);
return WrapMapper.ok(null, "配置文档删除成功");
} catch (BusinessException e) {
log.error("配置文档删除失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("配置文档删除异常: {}", e.getMessage(), e);
return WrapMapper.fail("配置文档删除失败");
}
}
/**
* 获取配置文档详情
*
* @param configDocumentId 配置文档ID
* @return 配置文档详情包装对象
*/
@GetMapping("/{configDocumentId}")
@Operation(summary = "获取配置文档详情", description = "根据ID获取配置文档的详细信息")
public Wrapper<ConfigDocumentVO> getConfigDocument(
@Parameter(description = "配置文档ID", required = true)
@PathVariable String configDocumentId) {
try {
ConfigDocumentVO result = configDocumentService.detail(configDocumentId);
return WrapMapper.ok(result, "获取配置文档详情成功");
} catch (BusinessException e) {
log.error("获取配置文档详情失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("获取配置文档详情异常: {}", e.getMessage(), e);
return WrapMapper.fail("获取配置文档详情失败");
}
}
/**
* 分页查询配置文档列表
*
* @param queryDTO 查询封装对象
* @return 分页结果包装对象
*/
@PostMapping("/page")
@Operation(summary = "分页查询配置文档", description = "分页查询配置文档列表")
public Wrapper<SearchResult<ConfigDocumentVO>> pageList(
@Parameter(description = "配置文档QueryDTO数据", required = true)
@RequestBody ConfigDocumentQueryDTO queryDTO) {
try {
SearchResult<ConfigDocumentVO> result = configDocumentService.pageList(queryDTO);
return WrapMapper.ok(result);
} catch (Exception e) {
log.error("查询配置文档列表异常: {}", e.getMessage(), e);
return WrapMapper.fail("查询配置文档列表失败");
}
}
/**
* 获取所有配置文档列表
*
* @param queryDTO 查询封装对象
* @return 配置文档列表包装对象
*/
@PostMapping("/options")
@Operation(summary = "获取所有配置文档", description = "获取所有配置文档的列表")
public Wrapper<List<ConfigDocumentVO>> options(
@Parameter(description = "配置文档QueryDTO数据", required = true)
@RequestBody ConfigDocumentQueryDTO queryDTO) {
try {
List<ConfigDocumentVO> result = configDocumentService.option(queryDTO);
return WrapMapper.ok(result, "获取所有配置文档成功");
} catch (Exception e) {
log.error("获取所有配置文档异常: {}", e.getMessage(), e);
return WrapMapper.fail("获取所有配置文档失败");
}
}
}

View File

@ -0,0 +1,171 @@
package com.example.demo.parser.controller;
import cn.zhxu.bs.SearchResult;
import com.example.demo.common.wrapper.WrapMapper;
import com.example.demo.common.wrapper.Wrapper;
import com.example.demo.common.exception.BusinessException;
import com.example.demo.parser.model.dto.ConfigValueDTO;
import com.example.demo.parser.model.dto.ConfigValueQueryDTO;
import com.example.demo.parser.model.vo.ConfigValueVO;
import com.example.demo.parser.service.ConfigValueService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 配置值控制器
* 提供配置值管理的RESTful API接口
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Slf4j
@RestController
@RequestMapping("/parser/config-values")
@RequiredArgsConstructor
@Tag(name = "配置值管理", description = "提供配置值管理的接口")
public class ConfigValueController {
private final ConfigValueService configValueService;
/**
* 创建配置值
*
* @param configValue 配置值数据
* @return 操作结果包装对象
*/
@PostMapping
@Operation(summary = "创建配置值", description = "创建新的配置值")
public Wrapper<ConfigValueVO> createConfigValue(
@Parameter(description = "配置值数据", required = true)
@RequestBody ConfigValueDTO configValue) {
try {
ConfigValueVO result = configValueService.create(configValue);
return WrapMapper.ok(result, "配置值创建成功");
} catch (BusinessException e) {
log.error("配置值创建失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("配置值创建异常: {}", e.getMessage(), e);
return WrapMapper.fail("配置值创建失败");
}
}
/**
* 更新配置值
*
* @param configValueId 配置值ID
* @param configValue 配置值数据
* @return 操作结果包装对象
*/
@PutMapping("/{configValueId}")
@Operation(summary = "更新配置值", description = "更新指定的配置值")
public Wrapper<ConfigValueVO> updateConfigValue(
@Parameter(description = "配置值ID", required = true)
@PathVariable String configValueId,
@Parameter(description = "配置值数据", required = true)
@RequestBody ConfigValueDTO configValue) {
try {
configValueService.update(configValue);
ConfigValueVO result = configValueService.detail(configValue.getId());
return WrapMapper.ok(result, "配置值更新成功");
} catch (BusinessException e) {
log.error("配置值更新失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("配置值更新异常: {}", e.getMessage(), e);
return WrapMapper.fail("配置值更新失败");
}
}
/**
* 删除配置值
*
* @param configValueId 配置值ID
* @return 操作结果包装对象
*/
@DeleteMapping("/{configValueId}")
@Operation(summary = "删除配置值", description = "删除指定的配置值")
public Wrapper<Void> deleteConfigValue(
@Parameter(description = "配置值ID", required = true)
@PathVariable String configValueId) {
try {
configValueService.delete(configValueId);
return WrapMapper.ok(null, "配置值删除成功");
} catch (BusinessException e) {
log.error("配置值删除失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("配置值删除异常: {}", e.getMessage(), e);
return WrapMapper.fail("配置值删除失败");
}
}
/**
* 获取配置值详情
*
* @param configValueId 配置值ID
* @return 配置值详情包装对象
*/
@GetMapping("/{configValueId}")
@Operation(summary = "获取配置值详情", description = "根据ID获取配置值的详细信息")
public Wrapper<ConfigValueVO> getConfigValue(
@Parameter(description = "配置值ID", required = true)
@PathVariable String configValueId) {
try {
ConfigValueVO result = configValueService.detail(configValueId);
return WrapMapper.ok(result, "获取配置值详情成功");
} catch (BusinessException e) {
log.error("获取配置值详情失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("获取配置值详情异常: {}", e.getMessage(), e);
return WrapMapper.fail("获取配置值详情失败");
}
}
/**
* 分页查询配置值列表
*
* @param queryDTO 查询封装对象
* @return 分页结果包装对象
*/
@PostMapping("/page")
@Operation(summary = "分页查询配置值", description = "分页查询配置值列表")
public Wrapper<SearchResult<ConfigValueVO>> pageList(
@Parameter(description = "配置值QueryDTO数据", required = true)
@RequestBody ConfigValueQueryDTO queryDTO) {
try {
SearchResult<ConfigValueVO> result = configValueService.pageList(queryDTO);
return WrapMapper.ok(result);
} catch (Exception e) {
log.error("查询配置值列表异常: {}", e.getMessage(), e);
return WrapMapper.fail("查询配置值列表失败");
}
}
/**
* 获取所有配置值列表
*
* @param queryDTO 查询封装对象
* @return 配置值列表包装对象
*/
@PostMapping("/options")
@Operation(summary = "获取所有配置值", description = "获取所有配置值的列表")
public Wrapper<List<ConfigValueVO>> options(
@Parameter(description = "配置值QueryDTO数据", required = true)
@RequestBody ConfigValueQueryDTO queryDTO) {
try {
List<ConfigValueVO> result = configValueService.option(queryDTO);
return WrapMapper.ok(result, "获取所有配置值成功");
} catch (Exception e) {
log.error("获取所有配置值异常: {}", e.getMessage(), e);
return WrapMapper.fail("获取所有配置值失败");
}
}
}

View File

@ -1,245 +1,259 @@
//package com.example.demo.parser.controller; package com.example.demo.parser.controller;
//
//import com.example.demo.common.wrapper.WrapMapper; import cn.zhxu.bs.SearchResult;
//import com.example.demo.common.wrapper.Wrapper; import com.example.demo.common.wrapper.WrapMapper;
//import com.example.demo.common.exception.BusinessException; import com.example.demo.common.wrapper.Wrapper;
//import com.example.demo.common.utils.FileUtil; import com.example.demo.common.exception.BusinessException;
//import com.example.demo.common.utils.XmlParserUtil; import com.example.demo.common.utils.FileUtil;
//import com.example.demo.parser.entity.FileRecordEntity; import com.example.demo.common.utils.XmlParserUtil;
//import com.example.demo.parser.model.dto.FileRecordDTO; import com.example.demo.parser.entity.FileRecordEntity;
//import com.example.demo.parser.model.vo.FileRecordVO; import com.example.demo.parser.model.dto.FileRecordDTO;
//import com.example.demo.parser.service.FileRecordService; import com.example.demo.parser.model.dto.FileRecordQueryDTO;
//import com.mybatisflex.core.paginate.Page; import com.example.demo.parser.model.vo.FileRecordVO;
//import io.swagger.v3.oas.annotations.Operation; import com.example.demo.parser.service.FileRecordService;
//import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation;
//import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Parameter;
//import lombok.RequiredArgsConstructor; import io.swagger.v3.oas.annotations.tags.Tag;
//import lombok.extern.slf4j.Slf4j; import lombok.RequiredArgsConstructor;
//import org.springframework.beans.factory.annotation.Value; import lombok.extern.slf4j.Slf4j;
//import org.springframework.web.bind.annotation.*; import org.springframework.beans.factory.annotation.Value;
//import org.springframework.web.multipart.MultipartFile; import org.springframework.web.bind.annotation.*;
// import org.springframework.web.multipart.MultipartFile;
//import java.io.File;
//import java.nio.file.Files; import java.io.File;
//import java.nio.file.Path; import java.nio.file.Path;
//import java.nio.file.Paths; import java.nio.file.Paths;
//import java.time.LocalDateTime; import java.util.Date;
//import java.util.List; import java.util.List;
//import java.util.UUID;
// /**
///** * 文件解析控制器
// * 文件解析控制器 * 提供XML文件上传解析和转换的RESTful API接口
// * 提供文件上传解析和转换的RESTful API接口 *
// * * @author 岳佳君 (2025年09月25日 16:30:00)
// * @author system * @version 1.0.0
// * @version 1.0 */
// */ @Slf4j
//@Slf4j @RestController
//@RestController @RequestMapping("/parser/files")
//@RequestMapping("/parser/files") @RequiredArgsConstructor
//@RequiredArgsConstructor @Tag(name = "文件解析管理", description = "提供XML文件上传、解析和转换的接口")
//@Tag(name = "文件解析管理", description = "提供XML文件上传、解析和转换的接口") public class FileParserController {
//public class FileParserController {
// private final FileRecordService fileRecordService;
// private final FileRecordService fileRecordService;
// @Value("${xml-parser.file.upload-dir:./upload}")
// @Value("${xml-parser.file.upload-dir:./upload}") private String uploadDir;
// private String uploadDir;
// @Value("${xml-parser.file.temp-dir:./temp}")
// @Value("${xml-parser.file.temp-dir:./temp}") private String tempDir;
// private String tempDir;
// /**
// /** * 上传XML文件
// * 上传XML文件 *
// * * @param file 上传的XML文件
// * @param file 上传的XML文件 * @return 操作结果包装对象
// * @return 操作结果 */
// */ @PostMapping("/upload")
// @PostMapping("/upload") @Operation(summary = "上传XML文件", description = "上传XML文件并进行解析准备")
// @Operation(summary = "上传XML文件", description = "上传XML文件并进行解析准备") public Wrapper<FileRecordVO> uploadFile(
// public Wrapper<FileRecordVO> uploadFile( @Parameter(description = "XML文件", required = true)
// @Parameter(description = "XML文件", required = true) @RequestParam("file") MultipartFile file) {
// @RequestParam("file") MultipartFile file) { try {
// try { // 验证文件类型
// // 验证文件类型 if (!isValidXmlFile(file)) {
// if (!isValidXmlFile(file)) { return WrapMapper.fail("请上传有效的XML文件");
// return WrapMapper.fail("请上传有效的XML文件"); }
// }
// // 创建上传目录
// // 创建上传目录 FileUtil.createDirectory(uploadDir);
// FileUtil.createDirectory(uploadDir);
// // 生成唯一文件名
// // 生成唯一文件名 String originalFilename = file.getOriginalFilename();
// String originalFilename = file.getOriginalFilename(); String uniqueFilename = FileUtil.generateUniqueFileName(originalFilename);
// String uniqueFilename = FileUtil.generateUniqueFileName(originalFilename); String filePath = Paths.get(uploadDir, uniqueFilename).toString();
// String filePath = Paths.get(uploadDir, uniqueFilename).toString();
// // 保存文件
// // 保存文件 file.transferTo(new File(filePath));
// file.transferTo(new File(filePath));
// // 创建文件记录
// // 创建文件记录 FileRecordDTO record = new FileRecordDTO();
// FileRecordDTO record = new FileRecordDTO(); record.setFileName(originalFilename);
// record.setFileName(originalFilename); record.setFilePath(filePath);
// record.setFilePath(filePath); record.setStatus("UPLOADED");
// record.setFileSize(file.getSize());
// record.setStatus("UPLOADED"); FileRecordVO result = fileRecordService.create(record);
// record.setProcessLog("文件上传成功");
// return WrapMapper.ok(result, "文件上传成功");
// String recordId = fileRecordService.create(record); } catch (BusinessException e) {
// FileRecordVO result = fileRecordService.getById(recordId); log.error("文件上传失败: {}", e.getMessage(), e);
// return WrapMapper.fail(e.getMessage());
// return WrapMapper.ok(result, "文件上传成功"); } catch (Exception e) {
// } catch (BusinessException e) { log.error("文件上传异常: {}", e.getMessage(), e);
// log.error("文件上传失败: {}", e.getMessage(), e); return WrapMapper.fail("文件上传失败");
// return WrapMapper.fail(e.getMessage()); }
// } catch (Exception e) { }
// log.error("文件上传异常: {}", e.getMessage(), e);
// return WrapMapper.fail("文件上传失败"); /**
// } * 解析XML文件
// } *
// * @param recordId 文件记录ID
// /** * @return 操作结果包装对象
// * 解析XML文件 */
// * @PostMapping("/parse/{recordId}")
// * @param recordId 文件记录ID @Operation(summary = "解析XML文件", description = "解析已上传的XML文件")
// * @return 操作结果 public Wrapper<FileRecordVO> parseFile(
// */ @Parameter(description = "文件记录ID", required = true)
// @PostMapping("/parse/{recordId}") @PathVariable String recordId) {
// @Operation(summary = "解析XML文件", description = "解析已上传的XML文件") try {
// public Wrapper<FileRecordVO> parseFile( FileRecordVO record = fileRecordService.detail(recordId);
// @Parameter(description = "文件记录ID", required = true) if (record == null) {
// @PathVariable String recordId) { return WrapMapper.fail("文件记录不存在");
// try { }
// FileRecordVO record = fileRecordService.getById(recordId);
// if (record == null) { // 更新状态为解析中 - 使用builder模式构建实体后调用updateById
// return WrapMapper.fail("文件记录不存在"); FileRecordEntity parsingEntity = FileRecordEntity.builder()
// } .id(recordId)
// .status("PARSING")
// // 更新状态为解析中 .processLog("开始解析XML文件")
// fileRecordService.updateStatus(recordId, "PARSING", "开始解析XML文件"); .processTime(new Date())
// .build();
// // 解析XML文件 fileRecordService.updateById(parsingEntity);
// String xmlFilePath = record.getFilePath();
// String txtFilePath = generateTxtFilePath(xmlFilePath); // 解析XML文件
// String xmlFilePath = record.getFilePath();
// try { String txtFilePath = generateTxtFilePath(xmlFilePath);
// XmlParserUtil.parseXmlToTxt(xmlFilePath, txtFilePath);
// try {
// // 更新状态为解析成功 XmlParserUtil.parseXmlToTxt(xmlFilePath, txtFilePath);
// fileRecordService.updateStatus(recordId, "PARSED", "XML文件解析成功");
// // 更新状态为解析成功 - 使用builder模式构建实体后调用updateById
// FileRecordVO result = fileRecordService.getById(recordId); FileRecordEntity parsedEntity = FileRecordEntity.builder()
// return WrapMapper.ok(result, "XML文件解析成功"); .id(recordId)
// .status("PARSED")
// } catch (Exception e) { .processLog("XML文件解析成功")
// // 更新状态为解析失败 .processTime(new Date())
// fileRecordService.updateStatus(recordId, "PARSE_FAILED", "XML文件解析失败: " + e.getMessage()); .build();
// throw new BusinessException("XML文件解析失败: " + e.getMessage()); fileRecordService.updateById(parsedEntity);
// }
// FileRecordVO result = fileRecordService.detail(recordId);
// } catch (BusinessException e) { return WrapMapper.ok(result, "XML文件解析成功");
// log.error("文件解析失败: {}", e.getMessage(), e);
// return WrapMapper.fail(e.getMessage()); } catch (Exception e) {
// } catch (Exception e) { // 更新状态为解析失败 - 使用builder模式构建实体后调用updateById
// log.error("文件解析异常: {}", e.getMessage(), e); FileRecordEntity failedEntity = FileRecordEntity.builder()
// return WrapMapper.fail("文件解析失败"); .id(recordId)
// } .status("PARSE_FAILED")
// } .processLog("XML文件解析失败: " + e.getMessage())
// .processTime(new Date())
// /** .build();
// * 获取文件记录详情 fileRecordService.updateById(failedEntity);
// * throw new BusinessException("XML文件解析失败: " + e.getMessage());
// * @param recordId 文件记录ID }
// * @return 文件记录详情
// */ } catch (BusinessException e) {
// @GetMapping("/{recordId}") log.error("文件解析失败: {}", e.getMessage(), e);
// @Operation(summary = "获取文件记录详情", description = "根据ID获取文件记录的详细信息") return WrapMapper.fail(e.getMessage());
// public Wrapper<FileRecordVO> getFileRecord( } catch (Exception e) {
// @Parameter(description = "文件记录ID", required = true) log.error("文件解析异常: {}", e.getMessage(), e);
// @PathVariable String recordId) { return WrapMapper.fail("文件解析失败");
// try { }
// FileRecordVO result = fileRecordService.getById(recordId); }
// return WrapMapper.ok(result, "获取文件记录详情成功");
// } catch (BusinessException e) { /**
// log.error("获取文件记录详情失败: {}", e.getMessage(), e); * 获取文件记录详情
// return WrapMapper.fail(e.getMessage()); *
// } catch (Exception e) { * @param recordId 文件记录ID
// log.error("获取文件记录详情异常: {}", e.getMessage(), e); * @return 文件记录详情包装对象
// return WrapMapper.fail("获取文件记录详情失败"); */
// } @GetMapping("/{recordId}")
// } @Operation(summary = "获取文件记录详情", description = "根据ID获取文件记录的详细信息")
// public Wrapper<FileRecordVO> getFileRecord(
// /** @Parameter(description = "文件记录ID", required = true)
// * 分页查询文件记录列表 @PathVariable String recordId) {
// * try {
// * @param pageNumber 页码 FileRecordVO result = fileRecordService.detail(recordId);
// * @param pageSize 每页大小 return WrapMapper.ok(result, "获取文件记录详情成功");
// * @return 分页结果 } catch (BusinessException e) {
// */ log.error("获取文件记录详情失败: {}", e.getMessage(), e);
// @GetMapping("/page") return WrapMapper.fail(e.getMessage());
// @Operation(summary = "分页查询文件记录", description = "分页查询文件记录列表") } catch (Exception e) {
// public Wrapper<Page<FileRecordVO>> pageList( log.error("获取文件记录详情异常: {}", e.getMessage(), e);
// @Parameter(description = "页码", example = "1") return WrapMapper.fail("获取文件记录详情失败");
// @RequestParam(defaultValue = "1") Integer pageNumber, }
// @Parameter(description = "每页大小", example = "10") }
// @RequestParam(defaultValue = "10") Integer pageSize) {
// try { /**
// Page<FileRecordVO> result = fileRecordService.pageList(pageNumber, pageSize); * 分页查询文件记录列表
// return WrapMapper.ok(result, "查询文件记录列表成功"); *
// } catch (Exception e) { * @param queryDTO 查询封装对象
// log.error("查询文件记录列表异常: {}", e.getMessage(), e); * @return 分页结果包装对象
// return WrapMapper.fail("查询文件记录列表失败"); */
// } @PostMapping("/page")
// } @Operation(summary = "分页查询文件记录", description = "分页查询文件记录列表")
// public Wrapper<SearchResult<FileRecordVO>> pageList(
// /** @Parameter(description = "文件记录QueryDTO数据", required = true)
// * 获取所有文件记录列表 @RequestBody FileRecordQueryDTO queryDTO) {
// * try {
// * @return 文件记录列表 SearchResult<FileRecordVO> result = fileRecordService.pageList(queryDTO);
// */ return WrapMapper.ok(result);
// @GetMapping("/list") } catch (Exception e) {
// @Operation(summary = "获取所有文件记录", description = "获取所有文件记录的列表") log.error("查询文件记录列表异常: {}", e.getMessage(), e);
// public Wrapper<List<FileRecordVO>> listAll() { return WrapMapper.fail("查询文件记录列表失败");
// try { }
// List<FileRecordVO> result = fileRecordService.listAll(); }
// return WrapMapper.ok(result, "获取所有文件记录成功");
// } catch (Exception e) { /**
// log.error("获取所有文件记录异常: {}", e.getMessage(), e); * 获取所有文件记录列表
// return WrapMapper.fail("获取所有文件记录失败"); *
// } * @param queryDTO 查询封装对象
// } * @return 文件记录列表包装对象
// */
// /** @PostMapping("/options")
// * 验证是否为有效的XML文件 @Operation(summary = "获取所有文件记录", description = "获取所有文件记录的列表")
// * public Wrapper<List<FileRecordVO>> options(
// * @param file 上传的文件 @Parameter(description = "文件记录QueryDTO数据", required = true)
// * @return 是否有效 @RequestBody FileRecordQueryDTO queryDTO) {
// */ try {
// private boolean isValidXmlFile(MultipartFile file) { List<FileRecordVO> result = fileRecordService.option(queryDTO);
// if (file == null || file.isEmpty()) { return WrapMapper.ok(result, "获取所有文件记录成功");
// return false; } catch (Exception e) {
// } log.error("获取所有文件记录异常: {}", e.getMessage(), e);
// return WrapMapper.fail("获取所有文件记录失败");
// String originalFilename = file.getOriginalFilename(); }
// if (originalFilename == null) { }
// return false;
// } /**
// * 验证是否为有效的XML文件
// // 检查文件扩展名 *
// String extension = FileUtil.getFileExtension(originalFilename); * @param file 上传的文件
// return "xml".equalsIgnoreCase(extension); * @return 是否有效
// } */
// private boolean isValidXmlFile(MultipartFile file) {
// /** if (file == null || file.isEmpty()) {
// * 生成TXT文件路径 return false;
// * }
// * @param xmlFilePath XML文件路径
// * @return TXT文件路径 String originalFilename = file.getOriginalFilename();
// */ if (originalFilename == null) {
// private String generateTxtFilePath(String xmlFilePath) { return false;
// Path xmlPath = Paths.get(xmlFilePath); }
// String xmlFileName = xmlPath.getFileName().toString();
// String txtFileName = xmlFileName.replace(".xml", ".txt"); // 检查文件扩展名
// return xmlPath.getParent().resolve(txtFileName).toString(); String extension = FileUtil.getFileExtension(originalFilename);
// } return "xml".equalsIgnoreCase(extension);
//} }
/**
* 生成TXT文件路径
*
* @param xmlFilePath XML文件路径
* @return TXT文件路径
*/
private String generateTxtFilePath(String xmlFilePath) {
Path xmlPath = Paths.get(xmlFilePath);
String xmlFileName = xmlPath.getFileName().toString();
String txtFileName = xmlFileName.replace(".xml", ".txt");
return xmlPath.getParent().resolve(txtFileName).toString();
}
}

View File

@ -0,0 +1,171 @@
package com.example.demo.parser.controller;
import cn.zhxu.bs.SearchResult;
import com.example.demo.common.wrapper.WrapMapper;
import com.example.demo.common.wrapper.Wrapper;
import com.example.demo.common.exception.BusinessException;
import com.example.demo.parser.model.dto.LevelConfigDTO;
import com.example.demo.parser.model.dto.LevelConfigQueryDTO;
import com.example.demo.parser.model.vo.LevelConfigVO;
import com.example.demo.parser.service.LevelConfigService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 层级配置控制器
* 提供层级配置管理的RESTful API接口
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Slf4j
@RestController
@RequestMapping("/parser/level-configs")
@RequiredArgsConstructor
@Tag(name = "层级配置管理", description = "提供层级配置管理的接口")
public class LevelConfigController {
private final LevelConfigService levelConfigService;
/**
* 创建层级配置
*
* @param levelConfig 层级配置数据
* @return 操作结果包装对象
*/
@PostMapping
@Operation(summary = "创建层级配置", description = "创建新的层级配置")
public Wrapper<LevelConfigVO> createLevelConfig(
@Parameter(description = "层级配置数据", required = true)
@RequestBody LevelConfigDTO levelConfig) {
try {
LevelConfigVO result = levelConfigService.create(levelConfig);
return WrapMapper.ok(result, "层级配置创建成功");
} catch (BusinessException e) {
log.error("层级配置创建失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("层级配置创建异常: {}", e.getMessage(), e);
return WrapMapper.fail("层级配置创建失败");
}
}
/**
* 更新层级配置
*
* @param levelConfigId 层级配置ID
* @param levelConfig 层级配置数据
* @return 操作结果包装对象
*/
@PutMapping("/{levelConfigId}")
@Operation(summary = "更新层级配置", description = "更新指定的层级配置")
public Wrapper<LevelConfigVO> updateLevelConfig(
@Parameter(description = "层级配置ID", required = true)
@PathVariable String levelConfigId,
@Parameter(description = "层级配置数据", required = true)
@RequestBody LevelConfigDTO levelConfig) {
try {
levelConfigService.update(levelConfig);
LevelConfigVO result = levelConfigService.detail(levelConfig.getId());
return WrapMapper.ok(result, "层级配置更新成功");
} catch (BusinessException e) {
log.error("层级配置更新失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("层级配置更新异常: {}", e.getMessage(), e);
return WrapMapper.fail("层级配置更新失败");
}
}
/**
* 删除层级配置
*
* @param levelConfigId 层级配置ID
* @return 操作结果包装对象
*/
@DeleteMapping("/{levelConfigId}")
@Operation(summary = "删除层级配置", description = "删除指定的层级配置")
public Wrapper<Void> deleteLevelConfig(
@Parameter(description = "层级配置ID", required = true)
@PathVariable String levelConfigId) {
try {
levelConfigService.delete(levelConfigId);
return WrapMapper.ok(null, "层级配置删除成功");
} catch (BusinessException e) {
log.error("层级配置删除失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("层级配置删除异常: {}", e.getMessage(), e);
return WrapMapper.fail("层级配置删除失败");
}
}
/**
* 获取层级配置详情
*
* @param levelConfigId 层级配置ID
* @return 层级配置详情包装对象
*/
@GetMapping("/{levelConfigId}")
@Operation(summary = "获取层级配置详情", description = "根据ID获取层级配置的详细信息")
public Wrapper<LevelConfigVO> getLevelConfig(
@Parameter(description = "层级配置ID", required = true)
@PathVariable String levelConfigId) {
try {
LevelConfigVO result = levelConfigService.detail(levelConfigId);
return WrapMapper.ok(result, "获取层级配置详情成功");
} catch (BusinessException e) {
log.error("获取层级配置详情失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("获取层级配置详情异常: {}", e.getMessage(), e);
return WrapMapper.fail("获取层级配置详情失败");
}
}
/**
* 分页查询层级配置列表
*
* @param queryDTO 查询封装对象
* @return 分页结果包装对象
*/
@PostMapping("/page")
@Operation(summary = "分页查询层级配置", description = "分页查询层级配置列表")
public Wrapper<SearchResult<LevelConfigVO>> pageList(
@Parameter(description = "层级配置QueryDTO数据", required = true)
@RequestBody LevelConfigQueryDTO queryDTO) {
try {
SearchResult<LevelConfigVO> result = levelConfigService.pageList(queryDTO);
return WrapMapper.ok(result);
} catch (Exception e) {
log.error("查询层级配置列表异常: {}", e.getMessage(), e);
return WrapMapper.fail("查询层级配置列表失败");
}
}
/**
* 获取所有层级配置列表
*
* @param queryDTO 查询封装对象
* @return 层级配置列表包装对象
*/
@PostMapping("/options")
@Operation(summary = "获取所有层级配置", description = "获取所有层级配置的列表")
public Wrapper<List<LevelConfigVO>> options(
@Parameter(description = "层级配置QueryDTO数据", required = true)
@RequestBody LevelConfigQueryDTO queryDTO) {
try {
List<LevelConfigVO> result = levelConfigService.option(queryDTO);
return WrapMapper.ok(result, "获取所有层级配置成功");
} catch (Exception e) {
log.error("获取所有层级配置异常: {}", e.getMessage(), e);
return WrapMapper.fail("获取所有层级配置失败");
}
}
}

View File

@ -1,188 +1,175 @@
//package com.example.demo.parser.controller; package com.example.demo.parser.controller;
//
//import com.example.demo.common.exception.BusinessException; import cn.zhxu.bs.SearchResult;
//import com.example.demo.common.wrapper.WrapMapper; import com.example.demo.common.wrapper.WrapMapper;
//import com.example.demo.common.wrapper.Wrapper; import com.example.demo.common.wrapper.Wrapper;
//import com.example.demo.parser.model.dto.MapperRuleDTO; import com.example.demo.common.exception.BusinessException;
//import com.example.demo.parser.model.vo.MapperRuleVO; import com.example.demo.parser.model.dto.MapperRuleDTO;
//import com.example.demo.parser.service.MapperRuleService; import com.example.demo.parser.model.dto.MapperRuleQueryDTO;
//import com.mybatisflex.core.paginate.Page; import com.example.demo.parser.model.vo.MapperRuleNoWithNullVO;
//import io.swagger.v3.oas.annotations.Operation; import com.example.demo.parser.model.vo.MapperRuleVO;
//import io.swagger.v3.oas.annotations.Parameter; import com.example.demo.parser.model.vo.ParseRuleNoWithNullVO;
//import io.swagger.v3.oas.annotations.tags.Tag; import com.example.demo.parser.service.MapperRuleService;
//import jakarta.validation.Valid; import io.swagger.v3.oas.annotations.Operation;
//import lombok.RequiredArgsConstructor; import io.swagger.v3.oas.annotations.Parameter;
//import lombok.extern.slf4j.Slf4j; import io.swagger.v3.oas.annotations.tags.Tag;
//import org.springframework.validation.annotation.Validated; import lombok.RequiredArgsConstructor;
//import org.springframework.web.bind.annotation.*; import lombok.extern.slf4j.Slf4j;
// import org.springframework.beans.BeanUtils;
//import java.util.List; import org.springframework.web.bind.annotation.*;
//
///** import java.util.List;
// * 映射规则控制器
// * 提供映射规则的RESTful API接口 /**
// * * 映射规则控制器
// * @author system * 提供XML映射规则管理的RESTful API接口
// * @version 1.0 *
// */ * @author 岳佳君 (2025年09月25日 16:30:00)
//@Slf4j * @version 1.0.0
//@RestController */
//@RequestMapping("/parser/mapper-rules") @Slf4j
//@RequiredArgsConstructor @RestController
//@Validated @RequestMapping("/parser/mapper-rules")
//@Tag(name = "映射规则管理", description = "提供XML到TXT映射规则的增删改查接口") @RequiredArgsConstructor
//public class MapperRuleController { @Tag(name = "映射规则管理", description = "提供XML映射规则管理的接口")
// public class MapperRuleController {
// private final MapperRuleService mapperRuleService;
// private final MapperRuleService mapperRuleService;
// /**
// * 创建映射规则 /**
// * * 创建映射规则
// * @param dto 映射规则数据传输对象 *
// * @return 操作结果 * @param rule 映射规则数据
// */ * @return 操作结果包装对象
// @PostMapping */
// @Operation(summary = "创建映射规则", description = "创建新的XML到TXT映射规则") @PostMapping
// public Wrapper<String> create(@Valid @RequestBody MapperRuleDTO dto) { @Operation(summary = "创建映射规则", description = "创建新的映射规则")
// try { public Wrapper<MapperRuleVO> createRule(
// String id = mapperRuleService.create(dto); @Parameter(description = "映射规则数据", required = true)
// return WrapMapper.ok(id, "创建映射规则成功"); @RequestBody MapperRuleDTO rule) {
// } catch (BusinessException e) { try {
// log.error("创建映射规则失败: {}", e.getMessage(), e); MapperRuleVO result = mapperRuleService.create(rule);
// return WrapMapper.fail(e.getMessage()); MapperRuleNoWithNullVO vo = new MapperRuleNoWithNullVO();
// } catch (Exception e) { BeanUtils.copyProperties(result, vo);
// log.error("创建映射规则异常: {}", e.getMessage(), e); return WrapMapper.ok(vo, "映射规则创建成功");
// return WrapMapper.fail("创建映射规则失败"); } catch (BusinessException e) {
// } log.error("映射规则创建失败: {}", e.getMessage(), e);
// } return WrapMapper.fail(e.getMessage());
// } catch (Exception e) {
// /** log.error("映射规则创建异常: {}", e.getMessage(), e);
// * 删除映射规则 return WrapMapper.fail("映射规则创建失败");
// * }
// * @param id 映射规则ID }
// * @return 操作结果
// */ /**
// @DeleteMapping("/{id}") * 更新映射规则
// @Operation(summary = "删除映射规则", description = "根据ID删除映射规则") *
// public Wrapper<Boolean> delete( * @param rule 映射规则数据
// @Parameter(description = "映射规则ID", required = true) * @return 操作结果包装对象
// @PathVariable String id) { */
// try { @PutMapping("/{ruleId}")
// boolean result = mapperRuleService.delete(id); @Operation(summary = "更新映射规则", description = "更新指定的映射规则")
// return WrapMapper.ok(result, "删除映射规则成功"); public Wrapper<MapperRuleVO> updateRule(
// } catch (BusinessException e) { @Parameter(description = "规则ID", required = true)
// log.error("删除映射规则失败: {}", e.getMessage(), e); @PathVariable String ruleId,
// return WrapMapper.fail(e.getMessage()); @Parameter(description = "映射规则数据", required = true)
// } catch (Exception e) { @RequestBody MapperRuleDTO rule) {
// log.error("删除映射规则异常: {}", e.getMessage(), e); try {
// return WrapMapper.fail("删除映射规则失败"); mapperRuleService.update(rule);
// } MapperRuleVO result = mapperRuleService.detail(rule.getId());
// } return WrapMapper.ok(result, "映射规则更新成功");
// } catch (BusinessException e) {
// /** log.error("映射规则更新失败: {}", e.getMessage(), e);
// * 更新映射规则 return WrapMapper.fail(e.getMessage());
// * } catch (Exception e) {
// * @param dto 映射规则数据传输对象 log.error("映射规则更新异常: {}", e.getMessage(), e);
// * @return 操作结果 return WrapMapper.fail("映射规则更新失败");
// */ }
// @PutMapping }
// @Operation(summary = "更新映射规则", description = "更新现有的映射规则")
// public Wrapper<Boolean> update(@Valid @RequestBody MapperRuleDTO dto) { /**
// try { * 删除映射规则
// boolean result = mapperRuleService.update(dto); *
// return WrapMapper.ok(result, "更新映射规则成功"); * @param ruleId 规则ID
// } catch (BusinessException e) { * @return 操作结果包装对象
// log.error("更新映射规则失败: {}", e.getMessage(), e); */
// return WrapMapper.fail(e.getMessage()); @DeleteMapping("/{ruleId}")
// } catch (Exception e) { @Operation(summary = "删除映射规则", description = "删除指定的映射规则")
// log.error("更新映射规则异常: {}", e.getMessage(), e); public Wrapper<Void> deleteRule(
// return WrapMapper.fail("更新映射规则失败"); @Parameter(description = "规则ID", required = true)
// } @PathVariable String ruleId) {
// } try {
// mapperRuleService.delete(ruleId);
// /** return WrapMapper.ok(null, "映射规则删除成功");
// * 根据ID获取映射规则详情 } catch (BusinessException e) {
// * log.error("映射规则删除失败: {}", e.getMessage(), e);
// * @param id 映射规则ID return WrapMapper.fail(e.getMessage());
// * @return 映射规则详情 } catch (Exception e) {
// */ log.error("映射规则删除异常: {}", e.getMessage(), e);
// @GetMapping("/{id}") return WrapMapper.fail("映射规则删除失败");
// @Operation(summary = "获取映射规则详情", description = "根据ID获取映射规则的详细信息") }
// public Wrapper<MapperRuleVO> getById( }
// @Parameter(description = "映射规则ID", required = true)
// @PathVariable String id) { /**
// try { * 获取映射规则详情
// MapperRuleVO result = mapperRuleService.getById(id); *
// return WrapMapper.ok(result, "获取映射规则详情成功"); * @param ruleId 规则ID
// } catch (BusinessException e) { * @return 映射规则详情包装对象
// log.error("获取映射规则详情失败: {}", e.getMessage(), e); */
// return WrapMapper.fail(e.getMessage()); @GetMapping("/{ruleId}")
// } catch (Exception e) { @Operation(summary = "获取映射规则详情", description = "根据ID获取映射规则的详细信息")
// log.error("获取映射规则详情异常: {}", e.getMessage(), e); public Wrapper<MapperRuleVO> getRule(
// return WrapMapper.fail("获取映射规则详情失败"); @Parameter(description = "规则ID", required = true)
// } @PathVariable String ruleId) {
// } try {
// MapperRuleVO result = mapperRuleService.detail(ruleId);
// /** return WrapMapper.ok(result, "获取映射规则详情成功");
// * 分页查询映射规则列表 } catch (BusinessException e) {
// * log.error("获取映射规则详情失败: {}", e.getMessage(), e);
// * @param pageNumber 页码 return WrapMapper.fail(e.getMessage());
// * @param pageSize 每页大小 } catch (Exception e) {
// * @return 分页结果 log.error("获取映射规则详情异常: {}", e.getMessage(), e);
// */ return WrapMapper.fail("获取映射规则详情失败");
// @GetMapping("/page") }
// @Operation(summary = "分页查询映射规则", description = "分页查询映射规则列表") }
// public Wrapper<Page<MapperRuleVO>> pageList(
// @Parameter(description = "页码", example = "1") /**
// @RequestParam(defaultValue = "1") Integer pageNumber, * 分页查询映射规则列表
// @Parameter(description = "每页大小", example = "10") *
// @RequestParam(defaultValue = "10") Integer pageSize) { * @param queryDTO 查询封装对象
// try { * @return 分页结果包装对象
// Page<MapperRuleVO> result = mapperRuleService.pageList(pageNumber, pageSize); */
// return WrapMapper.ok(result, "查询映射规则列表成功"); @PostMapping("/page")
// } catch (Exception e) { @Operation(summary = "分页查询映射规则", description = "分页查询映射规则列表")
// log.error("查询映射规则列表异常: {}", e.getMessage(), e); public Wrapper<SearchResult<MapperRuleVO>> pageList(
// return WrapMapper.fail("查询映射规则列表失败"); @Parameter(description = "映射规则QueryDTO数据", required = true)
// } @RequestBody MapperRuleQueryDTO queryDTO) {
// } try {
// SearchResult<MapperRuleVO> result = mapperRuleService.pageList(queryDTO);
// /** return WrapMapper.ok(result);
// * 根据解析规则ID获取映射规则列表 } catch (Exception e) {
// * log.error("查询映射规则列表异常: {}", e.getMessage(), e);
// * @param parseRuleId 解析规则ID return WrapMapper.fail("查询映射规则列表失败");
// * @return 映射规则列表 }
// */ }
// @GetMapping("/by-parse-rule/{parseRuleId}")
// @Operation(summary = "根据解析规则获取映射规则", description = "根据解析规则ID获取对应的映射规则列表") /**
// public Wrapper<List<MapperRuleVO>> getByParseRuleId( * 获取所有映射规则列表
// @Parameter(description = "解析规则ID", required = true) *
// @PathVariable String parseRuleId) { * @return 映射规则列表包装对象
// try { */
// List<MapperRuleVO> result = mapperRuleService.getByParseRuleId(parseRuleId); @PostMapping("/options")
// return WrapMapper.ok(result, "根据解析规则获取映射规则成功"); @Operation(summary = "获取所有映射规则", description = "获取所有映射规则的列表")
// } catch (BusinessException e) { public Wrapper<List<MapperRuleVO>> options(
// log.error("根据解析规则获取映射规则失败: {}", e.getMessage(), e); @Parameter(description = "映射规则QueryDTO数据", required = true)
// return WrapMapper.fail(e.getMessage()); @RequestBody MapperRuleQueryDTO queryDTO) {
// } catch (Exception e) { try {
// log.error("根据解析规则获取映射规则异常: {}", e.getMessage(), e); List<MapperRuleVO> result = mapperRuleService.option(queryDTO);
// return WrapMapper.fail("根据解析规则获取映射规则失败"); return WrapMapper.ok(result, "获取所有映射规则成功");
// } } catch (Exception e) {
// } log.error("获取所有映射规则异常: {}", e.getMessage(), e);
// return WrapMapper.fail("获取所有映射规则失败");
// /** }
// * 获取所有映射规则列表 }
// *
// * @return 映射规则列表 }
// */
// @GetMapping("/list")
// @Operation(summary = "获取所有映射规则", description = "获取所有映射规则的列表")
// public Wrapper<List<MapperRuleVO>> listAll() {
// try {
// List<MapperRuleVO> result = mapperRuleService.listAll();
// return WrapMapper.ok(result, "获取所有映射规则成功");
// } catch (Exception e) {
// log.error("获取所有映射规则异常: {}", e.getMessage(), e);
// return WrapMapper.fail("获取所有映射规则失败");
// }
// }
//}

View File

@ -1,188 +1,175 @@
//package com.example.demo.parser.controller; package com.example.demo.parser.controller;
//
//import cn.zhxu.bs.SearchResult; import cn.zhxu.bs.SearchResult;
//import com.example.demo.common.exception.BusinessException; import com.example.demo.common.wrapper.WrapMapper;
//import com.example.demo.common.wrapper.WrapMapper; import com.example.demo.common.wrapper.Wrapper;
//import com.example.demo.common.wrapper.Wrapper; import com.example.demo.common.exception.BusinessException;
//import com.example.demo.parser.entity.ParseRuleEntity; import com.example.demo.parser.model.dto.ParseRuleDTO;
//import com.example.demo.parser.model.dto.ParseRuleDTO; import com.example.demo.parser.model.dto.ParseRuleQueryDTO;
//import com.example.demo.parser.model.vo.ParseRuleVO; import com.example.demo.parser.model.vo.ParseRuleNoWithNullVO;
//import com.example.demo.parser.service.ParseRuleService; import com.example.demo.parser.model.vo.ParseRuleVO;
//import com.mybatisflex.core.paginate.Page; import com.example.demo.parser.service.ParseRuleService;
//import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
//import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
//import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
//import jakarta.validation.Valid; import lombok.RequiredArgsConstructor;
//import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j;
//import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils;
//import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*;
//import org.springframework.web.bind.annotation.*;
// import java.util.List;
//import java.util.List;
// /**
///** * 解析规则控制器
// * 解析规则控制器 * 提供XML解析规则管理的RESTful API接口
// * 提供解析规则的RESTful API接口 *
// * * @author 岳佳君 (2025年09月25日 16:30:00)
// * @author system * @version 1.0.0
// * @version 1.0 */
// */ @Slf4j
//@Slf4j @RestController
//@RestController @RequestMapping("/parser/rules")
//@RequestMapping("/parser/parse-rules") @RequiredArgsConstructor
//@RequiredArgsConstructor @Tag(name = "解析规则管理", description = "提供XML解析规则管理的接口")
//@Validated public class ParseRuleController {
//@Tag(name = "解析规则管理", description = "提供XML解析规则的增删改查接口")
//public class ParseRuleController { private final ParseRuleService parseRuleService;
//
// private final ParseRuleService parseRuleService; /**
// * 创建解析规则
// /** *
// * 创建解析规则 * @param rule 解析规则数据
// * * @return 操作结果包装对象
// * @param dto 解析规则数据传输对象 */
// * @return 操作结果 @PostMapping
// */ @Operation(summary = "创建解析规则", description = "创建新的解析规则")
// @PostMapping public Wrapper<ParseRuleNoWithNullVO> createRule(
// @Operation(summary = "创建解析规则", description = "创建新的XML解析规则") @Parameter(description = "解析规则数据", required = true)
// public Wrapper<String> create(@Valid @RequestBody ParseRuleDTO dto) { @RequestBody ParseRuleDTO rule) {
// try { try {
// String id = parseRuleService.create(dto); ParseRuleVO result = parseRuleService.create(rule);
// return WrapMapper.ok(id, "创建解析规则成功"); ParseRuleNoWithNullVO vo = new ParseRuleNoWithNullVO();
// } catch (BusinessException e) { BeanUtils.copyProperties(result, vo);
// log.error("创建解析规则失败: {}", e.getMessage(), e); return WrapMapper.ok(vo, "解析规则创建成功");
// return WrapMapper.fail(e.getMessage()); } catch (BusinessException e) {
// } catch (Exception e) { log.error("解析规则创建失败: {}", e.getMessage(), e);
// log.error("创建解析规则异常: {}", e.getMessage(), e); return WrapMapper.fail(e.getMessage());
// return WrapMapper.fail("创建解析规则失败"); } catch (Exception e) {
// } log.error("解析规则创建异常: {}", e.getMessage(), e);
// } return WrapMapper.fail("解析规则创建失败");
// }
// /** }
// * 删除解析规则
// * /**
// * @param id 解析规则ID * 更新解析规则
// * @return 操作结果 *
// */ * @param rule 解析规则数据
// @DeleteMapping("/{id}") * @return 操作结果包装对象
// @Operation(summary = "删除解析规则", description = "根据ID删除解析规则") */
// public Wrapper<Boolean> delete( @PutMapping("/{ruleId}")
// @Parameter(description = "解析规则ID", required = true) @Operation(summary = "更新解析规则", description = "更新指定的解析规则")
// @PathVariable String id) { public Wrapper<ParseRuleVO> updateRule(
// try { @Parameter(description = "规则ID", required = true)
// boolean result = parseRuleService.delete(id); @PathVariable String ruleId,
// return WrapMapper.ok(result, "删除解析规则成功"); @Parameter(description = "解析规则数据", required = true)
// } catch (BusinessException e) { @RequestBody ParseRuleDTO rule) {
// log.error("删除解析规则失败: {}", e.getMessage(), e); try {
// return WrapMapper.fail(e.getMessage()); parseRuleService.update(rule);
// } catch (Exception e) { ParseRuleVO result = parseRuleService.detail(rule.getId());
// log.error("删除解析规则异常: {}", e.getMessage(), e); return WrapMapper.ok(result, "解析规则更新成功");
// return WrapMapper.fail("删除解析规则失败"); } catch (BusinessException e) {
// } log.error("解析规则更新失败: {}", e.getMessage(), e);
// } return WrapMapper.fail(e.getMessage());
// } catch (Exception e) {
// /** log.error("解析规则更新异常: {}", e.getMessage(), e);
// * 更新解析规则 return WrapMapper.fail("解析规则更新失败");
// * }
// * @param dto 解析规则数据传输对象 }
// * @return 操作结果
// */ /**
// @PutMapping * 删除解析规则
// @Operation(summary = "更新解析规则", description = "更新现有的解析规则") *
// public Wrapper<Boolean> update(@Valid @RequestBody ParseRuleDTO dto) { * @param ruleId 规则ID
// try { * @return 操作结果包装对象
// boolean result = parseRuleService.update(dto); */
// return WrapMapper.ok(result, "更新解析规则成功"); @DeleteMapping("/{ruleId}")
// } catch (BusinessException e) { @Operation(summary = "删除解析规则", description = "删除指定的解析规则")
// log.error("更新解析规则失败: {}", e.getMessage(), e); public Wrapper<Void> deleteRule(
// return WrapMapper.fail(e.getMessage()); @Parameter(description = "规则ID", required = true)
// } catch (Exception e) { @PathVariable String ruleId) {
// log.error("更新解析规则异常: {}", e.getMessage(), e); try {
// return WrapMapper.fail("更新解析规则失败"); parseRuleService.delete(ruleId);
// } return WrapMapper.ok(null, "解析规则删除成功");
// } } catch (BusinessException e) {
// log.error("解析规则删除失败: {}", e.getMessage(), e);
// /** return WrapMapper.fail(e.getMessage());
// * 根据ID获取解析规则详情 } catch (Exception e) {
// * log.error("解析规则删除异常: {}", e.getMessage(), e);
// * @param id 解析规则ID return WrapMapper.fail("解析规则删除失败");
// * @return 解析规则详情 }
// */ }
// @GetMapping("/{id}")
// @Operation(summary = "获取解析规则详情", description = "根据ID获取解析规则的详细信息") /**
// public Wrapper<ParseRuleVO> getById( * 获取解析规则详情
// @Parameter(description = "解析规则ID", required = true) *
// @PathVariable String id) { * @param ruleId 规则ID
// try { * @return 解析规则详情包装对象
// ParseRuleVO result = parseRuleService.getById(id); */
// return WrapMapper.ok(result, "获取解析规则详情成功"); @GetMapping("/{ruleId}")
// } catch (BusinessException e) { @Operation(summary = "获取解析规则详情", description = "根据ID获取解析规则的详细信息")
// log.error("获取解析规则详情失败: {}", e.getMessage(), e); public Wrapper<ParseRuleVO> getRule(
// return WrapMapper.fail(e.getMessage()); @Parameter(description = "规则ID", required = true)
// } catch (Exception e) { @PathVariable String ruleId) {
// log.error("获取解析规则详情异常: {}", e.getMessage(), e); try {
// return WrapMapper.fail("获取解析规则详情失败"); ParseRuleVO result = parseRuleService.detail(ruleId);
// } return WrapMapper.ok(result, "获取解析规则详情成功");
// } } catch (BusinessException e) {
// log.error("获取解析规则详情失败: {}", e.getMessage(), e);
// /** return WrapMapper.fail(e.getMessage());
// * 分页查询解析规则列表 } catch (Exception e) {
// * log.error("获取解析规则详情异常: {}", e.getMessage(), e);
// * @param pageNumber 页码 return WrapMapper.fail("获取解析规则详情失败");
// * @param pageSize 每页大小 }
// * @return 分页结果 }
// */
// @GetMapping("/page") /**
// @Operation(summary = "分页查询解析规则", description = "分页查询解析规则列表") * 分页查询解析规则列表
// public Wrapper<Page<ParseRuleVO>> pageList( *
// @Parameter(description = "页码", example = "1") * @param queryDTO 查询封装对象
// @RequestParam(defaultValue = "1") Integer pageNumber, * @return 分页结果包装对象
// @Parameter(description = "每页大小", example = "10") */
// @RequestParam(defaultValue = "10") Integer pageSize) { @PostMapping("/page")
// try { @Operation(summary = "分页查询解析规则", description = "分页查询解析规则列表")
// Page<ParseRuleVO> result = parseRuleService.pageList(pageNumber, pageSize); public Wrapper<SearchResult<ParseRuleVO>> pageList(
// return WrapMapper.ok(result, "查询解析规则列表成功"); @Parameter(description = "解析规则QueryDTO数据", required = true)
// } catch (Exception e) { @RequestBody ParseRuleQueryDTO queryDTO) {
// log.error("查询解析规则列表异常: {}", e.getMessage(), e); try {
// return WrapMapper.fail("查询解析规则列表失败"); SearchResult<ParseRuleVO> result = parseRuleService.pageList(queryDTO);
// } return WrapMapper.ok(result);
// } } catch (Exception e) {
// log.error("查询解析规则列表异常: {}", e.getMessage(), e);
// /** return WrapMapper.fail("查询解析规则列表失败");
// * 获取所有解析规则列表 }
// * }
// * @return 解析规则列表
// */ /**
// @GetMapping("/list") * 获取所有解析规则列表
// @Operation(summary = "获取所有解析规则", description = "获取所有解析规则的列表") *
// public Wrapper<List<ParseRuleVO>> listAll() { * @param queryDTO 查询封装对象
// try { * @return 解析规则列表包装对象
// List<ParseRuleVO> result = parseRuleService.listAll(); */
// return WrapMapper.ok(result, "获取所有解析规则成功"); @PostMapping("/options")
// } catch (Exception e) { @Operation(summary = "获取所有解析规则", description = "获取所有解析规则的列表")
// log.error("获取所有解析规则异常: {}", e.getMessage(), e); public Wrapper<List<ParseRuleVO>> options(
// return WrapMapper.fail("获取所有解析规则失败"); @Parameter(description = "解析规则QueryDTO数据", required = true)
// } @RequestBody ParseRuleQueryDTO queryDTO) {
// } try {
// List<ParseRuleVO> result = parseRuleService.option(queryDTO);
// /** return WrapMapper.ok(result, "获取所有解析规则成功");
// * 根据XML标签名获取解析规则详情 } catch (Exception e) {
// * log.error("获取所有解析规则异常: {}", e.getMessage(), e);
// * @param xmlTag XML标签名 return WrapMapper.fail("获取所有解析规则失败");
// * @return 解析规则详情 }
// */ }
// @GetMapping("/by-xml-tag/{xmlTag}")
// @Operation(summary = "根据XML标签名获取解析规则详情") }
// public Wrapper<ParseRuleVO> getByXmlTag(@PathVariable String xmlTag) {
// log.info("根据XML标签名获取解析规则详情: {}", xmlTag);
//
// ParseRuleEntity entity = parseRuleService.getByXmlTag(xmlTag);
// if (entity == null) {
// return WrapMapper.fail("解析规则不存在: " + xmlTag);
// }
//
// // 通过getById方法获取VO对象
// ParseRuleVO result = parseRuleService.getById(entity.getId());
// return WrapMapper.ok(result);
// }
//}

View File

@ -0,0 +1,171 @@
package com.example.demo.parser.controller;
import cn.zhxu.bs.SearchResult;
import com.example.demo.common.wrapper.WrapMapper;
import com.example.demo.common.wrapper.Wrapper;
import com.example.demo.common.exception.BusinessException;
import com.example.demo.parser.model.dto.ValueConfigDTO;
import com.example.demo.parser.model.dto.ValueConfigQueryDTO;
import com.example.demo.parser.model.vo.ValueConfigVO;
import com.example.demo.parser.service.ValueConfigService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 值配置控制器
* 提供值配置管理的RESTful API接口
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Slf4j
@RestController
@RequestMapping("/parser/value-configs")
@RequiredArgsConstructor
@Tag(name = "值配置管理", description = "提供值配置管理的接口")
public class ValueConfigController {
private final ValueConfigService valueConfigService;
/**
* 创建值配置
*
* @param valueConfig 值配置数据
* @return 操作结果包装对象
*/
@PostMapping
@Operation(summary = "创建值配置", description = "创建新的值配置")
public Wrapper<ValueConfigVO> createValueConfig(
@Parameter(description = "值配置数据", required = true)
@RequestBody ValueConfigDTO valueConfig) {
try {
ValueConfigVO result = valueConfigService.create(valueConfig);
return WrapMapper.ok(result, "值配置创建成功");
} catch (BusinessException e) {
log.error("值配置创建失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("值配置创建异常: {}", e.getMessage(), e);
return WrapMapper.fail("值配置创建失败");
}
}
/**
* 更新值配置
*
* @param valueConfigId 值配置ID
* @param valueConfig 值配置数据
* @return 操作结果包装对象
*/
@PutMapping("/{valueConfigId}")
@Operation(summary = "更新值配置", description = "更新指定的值配置")
public Wrapper<ValueConfigVO> updateValueConfig(
@Parameter(description = "值配置ID", required = true)
@PathVariable String valueConfigId,
@Parameter(description = "值配置数据", required = true)
@RequestBody ValueConfigDTO valueConfig) {
try {
valueConfigService.update(valueConfig);
ValueConfigVO result = valueConfigService.detail(valueConfig.getId());
return WrapMapper.ok(result, "值配置更新成功");
} catch (BusinessException e) {
log.error("值配置更新失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("值配置更新异常: {}", e.getMessage(), e);
return WrapMapper.fail("值配置更新失败");
}
}
/**
* 删除值配置
*
* @param valueConfigId 值配置ID
* @return 操作结果包装对象
*/
@DeleteMapping("/{valueConfigId}")
@Operation(summary = "删除值配置", description = "删除指定的值配置")
public Wrapper<Void> deleteValueConfig(
@Parameter(description = "值配置ID", required = true)
@PathVariable String valueConfigId) {
try {
valueConfigService.delete(valueConfigId);
return WrapMapper.ok(null, "值配置删除成功");
} catch (BusinessException e) {
log.error("值配置删除失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("值配置删除异常: {}", e.getMessage(), e);
return WrapMapper.fail("值配置删除失败");
}
}
/**
* 获取值配置详情
*
* @param valueConfigId 值配置ID
* @return 值配置详情包装对象
*/
@GetMapping("/{valueConfigId}")
@Operation(summary = "获取值配置详情", description = "根据ID获取值配置的详细信息")
public Wrapper<ValueConfigVO> getValueConfig(
@Parameter(description = "值配置ID", required = true)
@PathVariable String valueConfigId) {
try {
ValueConfigVO result = valueConfigService.detail(valueConfigId);
return WrapMapper.ok(result, "获取值配置详情成功");
} catch (BusinessException e) {
log.error("获取值配置详情失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());
} catch (Exception e) {
log.error("获取值配置详情异常: {}", e.getMessage(), e);
return WrapMapper.fail("获取值配置详情失败");
}
}
/**
* 分页查询值配置列表
*
* @param queryDTO 查询封装对象
* @return 分页结果包装对象
*/
@PostMapping("/page")
@Operation(summary = "分页查询值配置", description = "分页查询值配置列表")
public Wrapper<SearchResult<ValueConfigVO>> pageList(
@Parameter(description = "值配置QueryDTO数据", required = true)
@RequestBody ValueConfigQueryDTO queryDTO) {
try {
SearchResult<ValueConfigVO> result = valueConfigService.pageList(queryDTO);
return WrapMapper.ok(result);
} catch (Exception e) {
log.error("查询值配置列表异常: {}", e.getMessage(), e);
return WrapMapper.fail("查询值配置列表失败");
}
}
/**
* 获取所有值配置列表
*
* @param queryDTO 查询封装对象
* @return 值配置列表包装对象
*/
@PostMapping("/options")
@Operation(summary = "获取所有值配置", description = "获取所有值配置的列表")
public Wrapper<List<ValueConfigVO>> options(
@Parameter(description = "值配置QueryDTO数据", required = true)
@RequestBody ValueConfigQueryDTO queryDTO) {
try {
List<ValueConfigVO> result = valueConfigService.option(queryDTO);
return WrapMapper.ok(result, "获取所有值配置成功");
} catch (Exception e) {
log.error("获取所有值配置异常: {}", e.getMessage(), e);
return WrapMapper.fail("获取所有值配置失败");
}
}
}

View File

@ -0,0 +1,79 @@
package com.example.demo.parser.entity;
import com.example.demo.common.config.orm.listener.FlexListener;
import com.example.demo.common.domain.BaseEntity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.RelationManyToOne;
import com.mybatisflex.annotation.Table;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 条件类型映射实体类
* 对应数据库中的condition_map表用于存储条件类型映射信息
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "条件类型映射")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Table(value = "condition_map",
onInsert = FlexListener.class,
onUpdate = FlexListener.class,
onSet = FlexListener.class
)
public class ConditionMapEntity extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 配置文档ID
*/
@Schema(description = "配置文档ID")
@Column(value = "config_document_id")
private String configDocumentId;
/**
* 条件键
*/
@Schema(description = "条件键")
@Column(value = "condition_key")
private String conditionKey;
/**
* 条件值
*/
@Schema(description = "条件值")
@Column(value = "condition_value")
private String conditionValue;
/**
* 描述信息
*/
@Schema(description = "描述信息")
private String description;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
@Column(value = "sort_order")
private Integer sortOrder;
/**
* 配置文档关联关系
*/
@RelationManyToOne(selfField = "configDocumentId", targetField = "id")
private ConfigDocumentEntity configDocument;
}

View File

@ -0,0 +1,71 @@
package com.example.demo.parser.entity;
import com.example.demo.common.config.orm.listener.FlexListener;
import com.example.demo.common.domain.BaseEntity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Table;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 配置文档实体类
* 对应数据库中的config_document表用于存储配置文档信息
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "配置文档")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Table(value = "config_document",
onInsert = FlexListener.class,
onUpdate = FlexListener.class,
onSet = FlexListener.class
)
public class ConfigDocumentEntity extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 全局备注信息
*/
@Schema(description = "全局备注信息")
private String globalComment;
/**
* 初始缩进配置
*/
@Schema(description = "初始缩进配置")
@Column(value = "initial_indent")
private String initialIndent;
/**
* 缩进空格数
*/
@Schema(description = "缩进空格数")
@Column(value = "indent_spaces")
private Integer indentSpaces;
/**
* 描述信息
*/
@Schema(description = "描述信息")
private String description;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
@Column(value = "sort_order")
private Integer sortOrder;
}

View File

@ -0,0 +1,107 @@
package com.example.demo.parser.entity;
import com.example.demo.common.config.orm.listener.FlexListener;
import com.example.demo.common.domain.BaseEntity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.RelationManyToOne;
import com.mybatisflex.annotation.Table;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 配置值实体类
* 对应数据库中的config_value表用于存储配置值信息
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "配置值")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Table(value = "config_value",
onInsert = FlexListener.class,
onUpdate = FlexListener.class,
onSet = FlexListener.class
)
public class ConfigValueEntity extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 值配置ID
*/
@Schema(description = "值配置ID")
@Column(value = "value_config_id")
private String valueConfigId;
/**
* 配置值JSON格式
*/
@Schema(description = "配置值")
@Column(value = "value_data")
private String valueData;
/**
* 值单位
*/
@Schema(description = "值单位")
@Column(value = "value_unit")
private String valueUnit;
/**
* 组合标志
*/
@Schema(description = "组合标志")
private Integer combined;
/**
* 正则表达式模式
*/
@Schema(description = "正则表达式模式")
@Column(value = "regex_pattern")
private String regexPattern;
/**
* 正则替换字符串
*/
@Schema(description = "正则替换字符串")
@Column(value = "regex_replacement")
private String regexReplacement;
/**
* 枚举映射配置JSON格式
*/
@Schema(description = "枚举映射配置")
@Column(value = "enum_mapping")
private String enumMapping;
/**
* 工具函数调用配置JSON格式
*/
@Schema(description = "工具函数调用配置")
@Column(value = "util_function")
private String utilFunction;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
@Column(value = "sort_order")
private Integer sortOrder;
/**
* 值配置关联关系
*/
@RelationManyToOne(selfField = "valueConfigId", targetField = "id")
private ValueConfigEntity valueConfig;
}

View File

@ -1,9 +1,11 @@
package com.example.demo.parser.entity; package com.example.demo.parser.entity;
import com.example.demo.common.domain.BaseEntity; import com.example.demo.common.domain.BaseEntity;
import com.example.demo.common.config.orm.listener.FlexListener;
import com.mybatisflex.annotation.Table; import com.mybatisflex.annotation.Table;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.io.Serial; import java.io.Serial;
@ -13,17 +15,22 @@ import java.util.Date;
* 文件记录实体类 * 文件记录实体类
* 对应数据库中的file_record表用于存储文件上传解析转换等操作记录 * 对应数据库中的file_record表用于存储文件上传解析转换等操作记录
* *
* @author system * @author 岳佳君 (2025年09月25日 19:42:26)
* @version 1.0 * @version 1.0.0
*/ */
@Schema(description = "文件记录") @Schema(description = "文件记录")
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Table("file_record") @Table(value = "file_record",
onInsert = FlexListener.class,
onUpdate = FlexListener.class,
onSet = FlexListener.class
)
public class FileRecordEntity extends BaseEntity { public class FileRecordEntity extends BaseEntity {
@Serial @Serial

View File

@ -0,0 +1,141 @@
package com.example.demo.parser.entity;
import com.example.demo.common.config.orm.listener.FlexListener;
import com.example.demo.common.domain.BaseEntity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.RelationManyToOne;
import com.mybatisflex.annotation.Table;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 层级配置实体类
* 对应数据库中的level_config表用于存储层级配置信息
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "层级配置")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Table(value = "level_config",
onInsert = FlexListener.class,
onUpdate = FlexListener.class,
onSet = FlexListener.class
)
public class LevelConfigEntity extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 配置文档ID
*/
@Schema(description = "配置文档ID")
@Column(value = "config_document_id")
private String configDocumentId;
/**
* 层级名称
*/
@Schema(description = "层级名称")
@Column(value = "level_name")
private String levelName;
/**
* 层级值循环索引号
*/
@Schema(description = "层级值循环索引号")
@Column(value = "level_loop_index")
private String levelLoopIndex;
/**
* 是否启用层级
*/
@Schema(description = "是否启用层级")
@Column(value = "enable_level")
private Integer enableLevel;
/**
* 层级值列表JSON格式
*/
@Schema(description = "层级值列表")
@Column(value = "level_values")
private String levelValues;
/**
* 层级注释说明
*/
@Schema(description = "层级注释说明")
private String comment;
/**
* 条件类型
*/
@Schema(description = "条件类型")
@Column(value = "condition_type")
private String conditionType;
/**
* 是否启用循环
*/
@Schema(description = "是否启用循环")
@Column(value = "enable_loop")
private Integer enableLoop;
/**
* 循环次数
*/
@Schema(description = "循环次数")
@Column(value = "loop_count")
private String loopCount;
/**
* 枚举映射配置JSON格式
*/
@Schema(description = "枚举映射配置")
@Column(value = "enum_mapping")
private String enumMapping;
/**
* 工具函数调用配置JSON格式
*/
@Schema(description = "工具函数调用配置")
@Column(value = "util_function")
private String utilFunction;
/**
* 父级ID
*/
@Schema(description = "父级ID")
@Column(value = "parent_id")
private String parentId;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
@Column(value = "sort_order")
private Integer sortOrder;
/**
* 配置文档关联关系
*/
@RelationManyToOne(selfField = "configDocumentId", targetField = "id")
private ConfigDocumentEntity configDocument;
/**
* 父级层级配置关联关系
*/
@RelationManyToOne(selfField = "parentId", targetField = "id")
private LevelConfigEntity parentLevelConfig;
}

View File

@ -1,9 +1,11 @@
package com.example.demo.parser.entity; package com.example.demo.parser.entity;
import com.example.demo.common.domain.BaseEntity; import com.example.demo.common.domain.BaseEntity;
import com.example.demo.common.config.orm.listener.FlexListener;
import com.mybatisflex.annotation.Table; import com.mybatisflex.annotation.Table;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.io.Serial; import java.io.Serial;
@ -12,17 +14,22 @@ import java.io.Serial;
* 映射规则实体类 * 映射规则实体类
* 对应数据库中的mapper_rule表用于存储XML到TXT的映射规则 * 对应数据库中的mapper_rule表用于存储XML到TXT的映射规则
* *
* @author system * @author 岳佳君 (2025年09月26日 14:53:50)
* @version 1.0 * @version 1.0.0
*/ */
@Schema(description = "映射规则") @Schema(description = "映射规则")
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Table("mapper_rule") @Table(value = "mapper_rule",
onInsert = FlexListener.class,
onUpdate = FlexListener.class,
onSet = FlexListener.class
)
public class MapperRuleEntity extends BaseEntity { public class MapperRuleEntity extends BaseEntity {
@Serial @Serial

View File

@ -1,9 +1,11 @@
package com.example.demo.parser.entity; package com.example.demo.parser.entity;
import com.example.demo.common.domain.BaseEntity; import com.example.demo.common.domain.BaseEntity;
import com.example.demo.common.config.orm.listener.FlexListener;
import com.mybatisflex.annotation.Table; import com.mybatisflex.annotation.Table;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.io.Serial; import java.io.Serial;
@ -12,17 +14,22 @@ import java.io.Serial;
* 解析规则实体类 * 解析规则实体类
* 对应数据库中的parse_rule表用于存储XML解析规则 * 对应数据库中的parse_rule表用于存储XML解析规则
* *
* @author system * @author 岳佳君 (2025年09月27日 11:35:15)
* @version 1.0 * @version 1.0.0
*/ */
@Schema(description = "解析规则") @Schema(description = "解析规则")
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Table("parse_rule") @Table(value = "parse_rule",
onInsert = FlexListener.class,
onUpdate = FlexListener.class,
onSet = FlexListener.class
)
public class ParseRuleEntity extends BaseEntity { public class ParseRuleEntity extends BaseEntity {
@Serial @Serial
@ -40,6 +47,18 @@ public class ParseRuleEntity extends BaseEntity {
@Schema(description = "标签类型") @Schema(description = "标签类型")
private String tagType; private String tagType;
/**
* TXT文件中的键名
*/
@Schema(description = "TXT文件中的键名")
private String txtKey;
/**
* 父级标签
*/
@Schema(description = "父级标签")
private String parentTag;
/** /**
* 是否允许为空0-不允许1-允许 * 是否允许为空0-不允许1-允许
*/ */
@ -51,4 +70,28 @@ public class ParseRuleEntity extends BaseEntity {
*/ */
@Schema(description = "节点路径") @Schema(description = "节点路径")
private String nodePath; private String nodePath;
/**
* 是否必填0-1-
*/
@Schema(description = "是否必填")
private Integer isRequired;
/**
* 默认值
*/
@Schema(description = "默认值")
private String defaultValue;
/**
* 描述信息
*/
@Schema(description = "描述信息")
private String description;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
private Integer sortOrder;
} }

View File

@ -0,0 +1,72 @@
package com.example.demo.parser.entity;
import com.example.demo.common.config.orm.listener.FlexListener;
import com.example.demo.common.domain.BaseEntity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.RelationManyToOne;
import com.mybatisflex.annotation.Table;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 值配置实体类
* 对应数据库中的value_config表用于存储值配置信息
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "值配置")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Table(value = "value_config",
onInsert = FlexListener.class,
onUpdate = FlexListener.class,
onSet = FlexListener.class
)
public class ValueConfigEntity extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 层级配置ID
*/
@Schema(description = "层级配置ID")
@Column(value = "level_config_id")
private String levelConfigId;
/**
* 值配置名称
*/
@Schema(description = "值配置名称")
@Column(value = "value_name")
private String valueName;
/**
* 值配置注释
*/
@Schema(description = "值配置注释")
private String comment;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
@Column(value = "sort_order")
private Integer sortOrder;
/**
* 层级配置关联关系
*/
@RelationManyToOne(selfField = "levelConfigId", targetField = "id")
private LevelConfigEntity levelConfig;
}

View File

@ -0,0 +1,16 @@
package com.example.demo.parser.mapper;
import com.example.demo.parser.entity.ConditionMapEntity;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 条件类型映射Mapper接口
* 提供条件类型映射的数据库操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Mapper
public interface ConditionMapMapper extends BaseMapper<ConditionMapEntity> {
}

View File

@ -0,0 +1,16 @@
package com.example.demo.parser.mapper;
import com.example.demo.parser.entity.ConfigDocumentEntity;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 配置文档Mapper接口
* 提供配置文档的数据库操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Mapper
public interface ConfigDocumentMapper extends BaseMapper<ConfigDocumentEntity> {
}

View File

@ -0,0 +1,16 @@
package com.example.demo.parser.mapper;
import com.example.demo.parser.entity.ConfigValueEntity;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 配置值Mapper接口
* 提供配置值的数据库操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Mapper
public interface ConfigValueMapper extends BaseMapper<ConfigValueEntity> {
}

View File

@ -8,8 +8,8 @@ import org.apache.ibatis.annotations.Mapper;
* 文件记录Mapper接口 * 文件记录Mapper接口
* 用于文件记录的数据库操作 * 用于文件记录的数据库操作
* *
* @author system * @author 岳佳君 (2025年09月23日 18:35:58)
* @version 1.0 * @version 1.0.0
*/ */
@Mapper @Mapper
public interface FileRecordMapper extends BaseMapper<FileRecordEntity> { public interface FileRecordMapper extends BaseMapper<FileRecordEntity> {

View File

@ -0,0 +1,16 @@
package com.example.demo.parser.mapper;
import com.example.demo.parser.entity.LevelConfigEntity;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 层级配置Mapper接口
* 提供层级配置的数据库操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Mapper
public interface LevelConfigMapper extends BaseMapper<LevelConfigEntity> {
}

View File

@ -8,8 +8,8 @@ import org.apache.ibatis.annotations.Mapper;
* 映射规则Mapper接口 * 映射规则Mapper接口
* 用于映射规则的数据库操作 * 用于映射规则的数据库操作
* *
* @author system * @author 岳佳君 (2025年09月23日 19:56:13)
* @version 1.0 * @version 1.0.0
*/ */
@Mapper @Mapper
public interface MapperRuleMapper extends BaseMapper<MapperRuleEntity> { public interface MapperRuleMapper extends BaseMapper<MapperRuleEntity> {

View File

@ -8,8 +8,8 @@ import org.apache.ibatis.annotations.Mapper;
* 解析规则Mapper接口 * 解析规则Mapper接口
* 用于解析规则的数据库操作 * 用于解析规则的数据库操作
* *
* @author system * @author 岳佳君 (2025年09月24日 21:13:19)
* @version 1.0 * @version 1.0.0
*/ */
@Mapper @Mapper
public interface ParseRuleMapper extends BaseMapper<ParseRuleEntity> { public interface ParseRuleMapper extends BaseMapper<ParseRuleEntity> {

View File

@ -0,0 +1,16 @@
package com.example.demo.parser.mapper;
import com.example.demo.parser.entity.ValueConfigEntity;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 值配置Mapper接口
* 提供值配置的数据库操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Mapper
public interface ValueConfigMapper extends BaseMapper<ValueConfigEntity> {
}

View File

@ -0,0 +1,60 @@
package com.example.demo.parser.model.dto;
import com.example.demo.common.domain.BaseDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 条件类型映射数据传输对象
* 用于条件类型映射的创建和更新操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "条件类型映射数据传输对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ConditionMapDTO extends BaseDTO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 配置文档ID
*/
@Schema(description = "配置文档ID")
private String configDocumentId;
/**
* 条件键
*/
@Schema(description = "条件键")
private String conditionKey;
/**
* 条件值
*/
@Schema(description = "条件值")
private String conditionValue;
/**
* 描述信息
*/
@Schema(description = "描述信息")
private String description;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
private Integer sortOrder;
}

View File

@ -0,0 +1,48 @@
package com.example.demo.parser.model.dto;
import com.example.demo.common.domain.BaseQueryDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 条件类型映射查询数据传输对象
* 用于条件类型映射的查询操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "条件类型映射查询数据传输对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ConditionMapQueryDTO extends BaseQueryDTO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 配置文档ID
*/
@Schema(description = "配置文档ID")
private String configDocumentId;
/**
* 条件键模糊查询
*/
@Schema(description = "条件键模糊查询")
private String conditionKey;
/**
* 条件值模糊查询
*/
@Schema(description = "条件值模糊查询")
private String conditionValue;
}

View File

@ -0,0 +1,60 @@
package com.example.demo.parser.model.dto;
import com.example.demo.common.domain.BaseDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 配置文档数据传输对象
* 用于配置文档的创建和更新操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "配置文档数据传输对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ConfigDocumentDTO extends BaseDTO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 全局备注信息
*/
@Schema(description = "全局备注信息")
private String globalComment;
/**
* 初始缩进配置
*/
@Schema(description = "初始缩进配置")
private String initialIndent;
/**
* 缩进空格数
*/
@Schema(description = "缩进空格数")
private Integer indentSpaces;
/**
* 描述信息
*/
@Schema(description = "描述信息")
private String description;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
private Integer sortOrder;
}

View File

@ -0,0 +1,42 @@
package com.example.demo.parser.model.dto;
import com.example.demo.common.domain.BaseQueryDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 配置文档查询数据传输对象
* 用于配置文档的查询操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "配置文档查询数据传输对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ConfigDocumentQueryDTO extends BaseQueryDTO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 全局备注信息模糊查询
*/
@Schema(description = "全局备注信息模糊查询")
private String globalComment;
/**
* 描述信息模糊查询
*/
@Schema(description = "描述信息模糊查询")
private String description;
}

View File

@ -0,0 +1,72 @@
package com.example.demo.parser.model.dto;
import com.example.demo.common.domain.BaseDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 配置值数据传输对象
* 用于配置值的创建和更新操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "配置值数据传输对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ConfigValueDTO extends BaseDTO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 值配置ID
*/
@Schema(description = "值配置ID")
private String valueConfigId;
/**
* 值数据
*/
@Schema(description = "值数据")
private String valueData;
/**
* 值单位
*/
@Schema(description = "值单位")
private String valueUnit;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
private Integer sortOrder;
/**
* 是否启用配置值
*/
@Schema(description = "是否启用配置值")
private Integer enableValue;
/**
* 条件类型
*/
@Schema(description = "条件类型")
private String conditionType;
/**
* 父级ID
*/
@Schema(description = "父级ID")
private String parentId;
}

View File

@ -0,0 +1,54 @@
package com.example.demo.parser.model.dto;
import com.example.demo.common.domain.BaseQueryDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 配置值查询数据传输对象
* 用于配置值的查询操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "配置值查询数据传输对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ConfigValueQueryDTO extends BaseQueryDTO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 值配置ID
*/
@Schema(description = "值配置ID")
private String valueConfigId;
/**
* 值数据模糊查询
*/
@Schema(description = "值数据模糊查询")
private String valueData;
/**
* 是否启用配置值
*/
@Schema(description = "是否启用配置值")
private Integer enableValue;
/**
* 条件类型
*/
@Schema(description = "条件类型")
private String conditionType;
}

View File

@ -8,6 +8,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.io.Serial; import java.io.Serial;
@ -18,15 +19,16 @@ import java.util.Date;
* 文件记录查询数据传输对象 * 文件记录查询数据传输对象
* 用于映射规则的创建和更新操作 * 用于映射规则的创建和更新操作
* *
* @author system * @author 岳佳君 (2025年09月26日 22:05:26)
* @version 1.0 * @version 1.0.0
*/ */
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class FileRecordDTO extends BaseDTO implements Serializable { public class FileRecordDTO extends BaseDTO {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -71,7 +73,7 @@ public class FileRecordDTO extends BaseDTO implements Serializable {
*/ */
@Schema(description = "文件状态") @Schema(description = "文件状态")
@DbField("status") @DbField("status")
private Integer status; private String status;
/** /**
* 上传时间开始 * 上传时间开始

View File

@ -4,6 +4,7 @@ import cn.zhxu.bs.bean.DbField;
import com.example.demo.common.domain.BaseQueryDTO; import com.example.demo.common.domain.BaseQueryDTO;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.io.Serial; import java.io.Serial;
@ -13,12 +14,13 @@ import java.util.Date;
* 文件记录查询数据传输对象 * 文件记录查询数据传输对象
* 用于封装文件记录的查询条件 * 用于封装文件记录的查询条件
* *
* @author system * @author 岳佳君 (2025年09月23日 17:40:27)
* @version 1.0 * @version 1.0.0
*/ */
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class FileRecordQueryDTO extends BaseQueryDTO { public class FileRecordQueryDTO extends BaseQueryDTO {

View File

@ -0,0 +1,108 @@
package com.example.demo.parser.model.dto;
import com.example.demo.common.domain.BaseDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 层级配置数据传输对象
* 用于层级配置的创建和更新操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "层级配置数据传输对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class LevelConfigDTO extends BaseDTO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 配置文档ID
*/
@Schema(description = "配置文档ID")
private String configDocumentId;
/**
* 层级名称
*/
@Schema(description = "层级名称")
private String levelName;
/**
* 层级值循环索引号
*/
@Schema(description = "层级值循环索引号")
private String levelLoopIndex;
/**
* 是否启用层级
*/
@Schema(description = "是否启用层级")
private Integer enableLevel;
/**
* 层级值列表JSON格式
*/
@Schema(description = "层级值列表")
private String levelValues;
/**
* 层级注释说明
*/
@Schema(description = "层级注释说明")
private String comment;
/**
* 条件类型
*/
@Schema(description = "条件类型")
private String conditionType;
/**
* 是否启用循环
*/
@Schema(description = "是否启用循环")
private Integer enableLoop;
/**
* 循环次数
*/
@Schema(description = "循环次数")
private String loopCount;
/**
* 枚举映射配置JSON格式
*/
@Schema(description = "枚举映射配置")
private String enumMapping;
/**
* 工具函数调用配置JSON格式
*/
@Schema(description = "工具函数调用配置")
private String utilFunction;
/**
* 父级ID
*/
@Schema(description = "父级ID")
private String parentId;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
private Integer sortOrder;
}

View File

@ -0,0 +1,54 @@
package com.example.demo.parser.model.dto;
import com.example.demo.common.domain.BaseQueryDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 层级配置查询数据传输对象
* 用于层级配置的查询操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "层级配置查询数据传输对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class LevelConfigQueryDTO extends BaseQueryDTO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 配置文档ID
*/
@Schema(description = "配置文档ID")
private String configDocumentId;
/**
* 层级名称模糊查询
*/
@Schema(description = "层级名称模糊查询")
private String levelName;
/**
* 条件类型
*/
@Schema(description = "条件类型")
private String conditionType;
/**
* 是否启用层级
*/
@Schema(description = "是否启用层级")
private Integer enableLevel;
}

View File

@ -6,6 +6,7 @@ import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.io.Serial; import java.io.Serial;
@ -15,17 +16,18 @@ import java.io.Serializable;
* 映射规则数据传输对象 * 映射规则数据传输对象
* 用于映射规则的创建和更新操作 * 用于映射规则的创建和更新操作
* *
* @author system * @author 岳佳君 (2025年09月24日 11:06:33)
* @version 1.0 * @version 1.0.0
*/ */
@Schema(description = "映射规则数据传输对象") @Schema(description = "映射规则数据传输对象")
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class MapperRuleDTO extends BaseDTO implements Serializable { public class MapperRuleDTO extends BaseDTO {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -65,4 +67,11 @@ public class MapperRuleDTO extends BaseDTO implements Serializable {
@NotNull(message = "排序顺序不能为空") @NotNull(message = "排序顺序不能为空")
@Schema(description = "排序顺序") @Schema(description = "排序顺序")
private Integer sortOrder; private Integer sortOrder;
/**
* 映射类型
*/
@Size(max = 50, message = "映射类型不能超过50个字符")
@Schema(description = "映射类型")
private String mappingType;
} }

View File

@ -4,6 +4,7 @@ import com.example.demo.common.domain.BaseQueryDTO;
import cn.zhxu.bs.bean.DbField; import cn.zhxu.bs.bean.DbField;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.io.Serial; import java.io.Serial;
@ -13,17 +14,18 @@ import java.io.Serializable;
* 映射规则查询数据传输对象 * 映射规则查询数据传输对象
* 用于封装映射规则的查询条件 * 用于封装映射规则的查询条件
* *
* @author system * @author 岳佳君 (2025年09月27日 18:04:23)
* @version 1.0 * @version 1.0.0
*/ */
@Schema(description = "映射规则查询数据传输对象") @Schema(description = "映射规则查询数据传输对象")
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class MapperRuleQueryDTO extends BaseQueryDTO implements Serializable { public class MapperRuleQueryDTO extends BaseQueryDTO {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.io.Serial; import java.io.Serial;
@ -14,17 +15,18 @@ import java.io.Serializable;
* 解析规则数据传输对象 * 解析规则数据传输对象
* 用于解析规则的创建和更新操作 * 用于解析规则的创建和更新操作
* *
* @author system * @author 岳佳君 (2025年09月23日 21:21:27)
* @version 1.0 * @version 1.0.0
*/ */
@Schema(description = "解析规则数据传输对象") @Schema(description = "解析规则数据传输对象")
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class ParseRuleDTO extends BaseDTO implements Serializable { public class ParseRuleDTO extends BaseDTO {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -58,4 +60,11 @@ public class ParseRuleDTO extends BaseDTO implements Serializable {
@Size(max = 255, message = "节点路径不能超过255个字符") @Size(max = 255, message = "节点路径不能超过255个字符")
@Schema(description = "节点路径") @Schema(description = "节点路径")
private String nodePath; private String nodePath;
/**
* TXT文件中的键名
*/
@Size(max = 100, message = "TXT文件中的键名不能超过100个字符")
@Schema(description = "TXT文件中的键名")
private String txtKey;
} }

View File

@ -4,6 +4,7 @@ import com.example.demo.common.domain.BaseQueryDTO;
import cn.zhxu.bs.bean.DbField; import cn.zhxu.bs.bean.DbField;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.io.Serial; import java.io.Serial;
@ -13,17 +14,18 @@ import java.io.Serializable;
* 解析规则查询数据传输对象 * 解析规则查询数据传输对象
* 用于封装解析规则的查询条件 * 用于封装解析规则的查询条件
* *
* @author system * @author 岳佳君 (2025年09月23日 18:05:25)
* @version 1.0 * @version 1.0.0
*/ */
@Schema(description = "解析规则查询数据传输对象") @Schema(description = "解析规则查询数据传输对象")
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class ParseRuleQueryDTO extends BaseQueryDTO implements Serializable { public class ParseRuleQueryDTO extends BaseQueryDTO {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -0,0 +1,72 @@
package com.example.demo.parser.model.dto;
import com.example.demo.common.domain.BaseDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 值配置数据传输对象
* 用于值配置的创建和更新操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "值配置数据传输对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ValueConfigDTO extends BaseDTO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 层级配置ID
*/
@Schema(description = "层级配置ID")
private String levelConfigId;
/**
* 值名称
*/
@Schema(description = "值名称")
private String valueName;
/**
* 值注释说明
*/
@Schema(description = "值注释说明")
private String comment;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
private Integer sortOrder;
/**
* 是否启用值配置
*/
@Schema(description = "是否启用值配置")
private Integer enableValue;
/**
* 条件类型
*/
@Schema(description = "条件类型")
private String conditionType;
/**
* 父级ID
*/
@Schema(description = "父级ID")
private String parentId;
}

View File

@ -0,0 +1,54 @@
package com.example.demo.parser.model.dto;
import com.example.demo.common.domain.BaseQueryDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 值配置查询数据传输对象
* 用于值配置的查询操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "值配置查询数据传输对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ValueConfigQueryDTO extends BaseQueryDTO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 层级配置ID
*/
@Schema(description = "层级配置ID")
private String levelConfigId;
/**
* 值名称模糊查询
*/
@Schema(description = "值名称模糊查询")
private String valueName;
/**
* 是否启用值配置
*/
@Schema(description = "是否启用值配置")
private Integer enableValue;
/**
* 条件类型
*/
@Schema(description = "条件类型")
private String conditionType;
}

View File

@ -0,0 +1,65 @@
package com.example.demo.parser.model.vo;
import cn.zhxu.bs.bean.SearchBean;
import com.example.demo.common.domain.BaseVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 条件类型映射视图对象
* 用于向前端返回条件类型映射信息
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "条件类型映射视图对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SearchBean(
tables = "condition_map a",
autoMapTo = "a"
)
public class ConditionMapVO extends BaseVO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 配置文档ID
*/
@Schema(description = "配置文档ID")
private String configDocumentId;
/**
* 条件键
*/
@Schema(description = "条件键")
private String conditionKey;
/**
* 条件值
*/
@Schema(description = "条件值")
private String conditionValue;
/**
* 描述信息
*/
@Schema(description = "描述信息")
private String description;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
private Integer sortOrder;
}

View File

@ -0,0 +1,65 @@
package com.example.demo.parser.model.vo;
import cn.zhxu.bs.bean.SearchBean;
import com.example.demo.common.domain.BaseVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 配置文档视图对象
* 用于向前端返回配置文档信息
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "配置文档视图对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SearchBean(
tables = "config_document a",
autoMapTo = "a"
)
public class ConfigDocumentVO extends BaseVO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 全局备注信息
*/
@Schema(description = "全局备注信息")
private String globalComment;
/**
* 初始缩进配置
*/
@Schema(description = "初始缩进配置")
private String initialIndent;
/**
* 缩进空格数
*/
@Schema(description = "缩进空格数")
private Integer indentSpaces;
/**
* 描述信息
*/
@Schema(description = "描述信息")
private String description;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
private Integer sortOrder;
}

View File

@ -0,0 +1,77 @@
package com.example.demo.parser.model.vo;
import cn.zhxu.bs.bean.SearchBean;
import com.example.demo.common.domain.BaseVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 配置值视图对象
* 用于向前端返回配置值信息
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "配置值视图对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SearchBean(
tables = "config_value a",
autoMapTo = "a"
)
public class ConfigValueVO extends BaseVO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 值配置ID
*/
@Schema(description = "值配置ID")
private String valueConfigId;
/**
* 值数据
*/
@Schema(description = "值数据")
private String valueData;
/**
* 值单位
*/
@Schema(description = "值单位")
private String valueUnit;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
private Integer sortOrder;
/**
* 是否启用配置值
*/
@Schema(description = "是否启用配置值")
private Integer enableValue;
/**
* 条件类型
*/
@Schema(description = "条件类型")
private String conditionType;
/**
* 父级ID
*/
@Schema(description = "父级ID")
private String parentId;
}

View File

@ -0,0 +1,32 @@
package com.example.demo.parser.model.vo;
import cn.zhxu.bs.bean.SearchBean;
import com.example.demo.common.filter.CustomJsonFilter;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
/**
* 文件记录视图对象
* 用于向前端返回文件记录数据
*
* @author 岳佳君 (2025年09月23日 16:21:17)
* @version 1.0.0
*/
@Schema(description = "文件记录视图对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SearchBean(
tables = "file_record a",
autoMapTo = "a"
)
@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = CustomJsonFilter.class)
public class FileRecordNoWithNullVO extends FileRecordVO {
// ignore
}

View File

@ -5,6 +5,7 @@ import cn.zhxu.bs.bean.SearchBean;
import com.fhs.core.trans.vo.TransPojo; import com.fhs.core.trans.vo.TransPojo;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
@ -17,18 +18,19 @@ import java.util.Date;
* 文件记录视图对象 * 文件记录视图对象
* 用于向前端返回文件记录数据 * 用于向前端返回文件记录数据
* *
* @author system * @author 岳佳君 (2025年09月23日 16:21:17)
* @version 1.0 * @version 1.0.0
*/ */
@Schema(description = "文件记录视图对象") @Schema(description = "文件记录视图对象")
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@SearchBean( @SearchBean(
tables = "file_record", tables = "file_record a",
autoMapTo = "a" autoMapTo = "a"
) )
public class FileRecordVO extends BaseVO implements TransPojo, Serializable { public class FileRecordVO extends BaseVO implements TransPojo, Serializable {

View File

@ -0,0 +1,113 @@
package com.example.demo.parser.model.vo;
import cn.zhxu.bs.bean.SearchBean;
import com.example.demo.common.domain.BaseVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 层级配置视图对象
* 用于向前端返回层级配置信息
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "层级配置视图对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SearchBean(
tables = "level_config a",
autoMapTo = "a"
)
public class LevelConfigVO extends BaseVO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 配置文档ID
*/
@Schema(description = "配置文档ID")
private String configDocumentId;
/**
* 层级名称
*/
@Schema(description = "层级名称")
private String levelName;
/**
* 层级值循环索引号
*/
@Schema(description = "层级值循环索引号")
private String levelLoopIndex;
/**
* 是否启用层级
*/
@Schema(description = "是否启用层级")
private Integer enableLevel;
/**
* 层级值列表JSON格式
*/
@Schema(description = "层级值列表")
private String levelValues;
/**
* 层级注释说明
*/
@Schema(description = "层级注释说明")
private String comment;
/**
* 条件类型
*/
@Schema(description = "条件类型")
private String conditionType;
/**
* 是否启用循环
*/
@Schema(description = "是否启用循环")
private Integer enableLoop;
/**
* 循环次数
*/
@Schema(description = "循环次数")
private String loopCount;
/**
* 枚举映射配置JSON格式
*/
@Schema(description = "枚举映射配置")
private String enumMapping;
/**
* 工具函数调用配置JSON格式
*/
@Schema(description = "工具函数调用配置")
private String utilFunction;
/**
* 父级ID
*/
@Schema(description = "父级ID")
private String parentId;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
private Integer sortOrder;
}

View File

@ -0,0 +1,32 @@
package com.example.demo.parser.model.vo;
import cn.zhxu.bs.bean.SearchBean;
import com.example.demo.common.filter.CustomJsonFilter;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
/**
* 映射规则视图对象
* 用于向前端返回映射规则数据
*
* @author 岳佳君 (2025年09月26日 21:44:29)
* @version 1.0.0
*/
@Schema(description = "映射规则视图对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SearchBean(
tables = "mapper_rule a",
autoMapTo = "a"
)
@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = CustomJsonFilter.class)
public class MapperRuleNoWithNullVO extends MapperRuleVO {
// ignore
}

View File

@ -5,6 +5,7 @@ import cn.zhxu.bs.bean.SearchBean;
import com.fhs.core.trans.vo.TransPojo; import com.fhs.core.trans.vo.TransPojo;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.io.Serial; import java.io.Serial;
@ -14,18 +15,19 @@ import java.io.Serializable;
* 映射规则视图对象 * 映射规则视图对象
* 用于向前端返回映射规则数据 * 用于向前端返回映射规则数据
* *
* @author system * @author 岳佳君 (2025年09月26日 21:44:29)
* @version 1.0 * @version 1.0.0
*/ */
@Schema(description = "映射规则视图对象") @Schema(description = "映射规则视图对象")
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@SearchBean( @SearchBean(
tables = "mapper_rule", tables = "mapper_rule a",
autoMapTo = "a" autoMapTo = "a"
) )
public class MapperRuleVO extends BaseVO implements TransPojo, Serializable { public class MapperRuleVO extends BaseVO implements TransPojo, Serializable {

View File

@ -0,0 +1,32 @@
package com.example.demo.parser.model.vo;
import cn.zhxu.bs.bean.SearchBean;
import com.example.demo.common.filter.CustomJsonFilter;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
/**
* 解析规则视图对象
* 用于向前端返回解析规则数据
*
* @author 岳佳君 (2025年09月26日 14:30:51)
* @version 1.0.0
*/
@Schema(description = "解析规则视图对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SearchBean(
tables = "parse_rule a",
autoMapTo = "a"
)
@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = CustomJsonFilter.class)
public class ParseRuleNoWithNullVO extends ParseRuleVO {
// ignore
}

View File

@ -5,6 +5,7 @@ import cn.zhxu.bs.bean.SearchBean;
import com.fhs.core.trans.vo.TransPojo; import com.fhs.core.trans.vo.TransPojo;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.io.Serial; import java.io.Serial;
@ -14,18 +15,19 @@ import java.io.Serializable;
* 解析规则视图对象 * 解析规则视图对象
* 用于向前端返回解析规则数据 * 用于向前端返回解析规则数据
* *
* @author system * @author 岳佳君 (2025年09月26日 14:30:51)
* @version 1.0 * @version 1.0.0
*/ */
@Schema(description = "解析规则视图对象") @Schema(description = "解析规则视图对象")
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@SearchBean( @SearchBean(
tables = "parse_rule", tables = "parse_rule a",
autoMapTo = "a" autoMapTo = "a"
) )
public class ParseRuleVO extends BaseVO implements TransPojo, Serializable { public class ParseRuleVO extends BaseVO implements TransPojo, Serializable {

View File

@ -0,0 +1,77 @@
package com.example.demo.parser.model.vo;
import cn.zhxu.bs.bean.SearchBean;
import com.example.demo.common.domain.BaseVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import java.io.Serial;
/**
* 值配置视图对象
* 用于向前端返回值配置信息
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Schema(description = "值配置视图对象")
@Getter
@Setter
@SuperBuilder
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SearchBean(
tables = "value_config a",
autoMapTo = "a"
)
public class ValueConfigVO extends BaseVO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 层级配置ID
*/
@Schema(description = "层级配置ID")
private String levelConfigId;
/**
* 值名称
*/
@Schema(description = "值名称")
private String valueName;
/**
* 值注释说明
*/
@Schema(description = "值注释说明")
private String comment;
/**
* 排序顺序
*/
@Schema(description = "排序顺序")
private Integer sortOrder;
/**
* 是否启用值配置
*/
@Schema(description = "是否启用值配置")
private Integer enableValue;
/**
* 条件类型
*/
@Schema(description = "条件类型")
private String conditionType;
/**
* 父级ID
*/
@Schema(description = "父级ID")
private String parentId;
}

View File

@ -0,0 +1,34 @@
package com.example.demo.parser.process.constant;
/**
* 解析处理常量类
* 定义XML解析和TXT转换过程中使用的常量
*
* @author 岳佳君 (2025年09月29日 09:58:32)
* @version 1.0.0
*/
public final class ParserProcessConstant {
/** 字符串模板常量 */
public static final class ST {
public static final String LOG_GROUP_LINE = String.format(" %s> %s <%s", "=".repeat(20), "%s","=".repeat(20));
public static final String NAME_WITH_INDEX = "%s_%0";
}
/** 单个字符 */
public static final class CHAR {
public static final String CHAR_D = "d";
public static final String CHAR_S = "s";
}
/** 字段名称 */
public static final class Field {
}
}

View File

@ -1,11 +1,14 @@
package com.example.demo.draft.demo043.core; package com.example.demo.parser.process.core;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.example.demo.draft.demo043.domain.ConfigValue; import com.alibaba.fastjson2.JSON;
import com.example.demo.draft.demo043.domain.LevelConfig; import com.example.demo.parser.process.constant.ParserProcessConstant;
import com.example.demo.draft.demo043.domain.ValueConfig; import com.example.demo.parser.process.domain.ConfigValue;
import com.example.demo.draft.demo043.util.FormatUtil; import com.example.demo.parser.process.domain.LevelConfig;
import com.example.demo.parser.process.domain.ValueConfig;
import com.example.demo.parser.process.util.FormatUtil;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.*; import java.util.*;
@ -24,7 +27,10 @@ import java.util.regex.Pattern;
* <li>枚举映射转换</li> * <li>枚举映射转换</li>
* <li>工具函数调用</li> * <li>工具函数调用</li>
* </ul> * </ul>
* @author 岳佳君 (2025年09月27日 19:54:24)
* @version 1.0.0
*/ */
@Slf4j
public class EnhancedConfigProcessor { public class EnhancedConfigProcessor {
/** /**
@ -60,7 +66,7 @@ public class EnhancedConfigProcessor {
String newValue; String newValue;
if (loopCount >= 2) { if (loopCount >= 2) {
// 当loopCount大于等于2时添加带序号的后缀根据最大位数自动补零 // 当loopCount大于等于2时添加带序号的后缀根据最大位数自动补零
newValue = String.format("%s_%0" + maxDigits + "d", processedConfig.getValues().getFirst(), i); newValue = String.format(ParserProcessConstant.ST.NAME_WITH_INDEX + maxDigits + ParserProcessConstant.CHAR.CHAR_D, processedConfig.getValues().getFirst(), i);
} else { } else {
// 当loopCount等于1时不添加后缀编号直接使用原始值 // 当loopCount等于1时不添加后缀编号直接使用原始值
newValue = processedConfig.getValues().getFirst(); newValue = processedConfig.getValues().getFirst();
@ -220,6 +226,10 @@ public class EnhancedConfigProcessor {
// 1. 应用正则表达式 // 1. 应用正则表达式
if (configValue.getRegexPattern() != null && configValue.getRegexReplacement() != null) { if (configValue.getRegexPattern() != null && configValue.getRegexReplacement() != null) {
System.out.println();
log.info("{}", String.format(ParserProcessConstant.ST.LOG_GROUP_LINE, "应用正则表达式"));
log.info("RegexPattern = {}", configValue.getRegexPattern());
log.info("RegexReplacement = {}", configValue.getRegexReplacement());
try { try {
Pattern pattern = Pattern.compile(configValue.getRegexPattern()); Pattern pattern = Pattern.compile(configValue.getRegexPattern());
Matcher matcher = pattern.matcher(strValue); Matcher matcher = pattern.matcher(strValue);
@ -230,12 +240,23 @@ public class EnhancedConfigProcessor {
} }
// 2. 应用枚举映射 // 2. 应用枚举映射
if (configValue.getEnumMapping() != null && configValue.getEnumMapping().containsKey(strValue)) { if (configValue.getEnumMapping() != null) {
strValue = configValue.getEnumMapping().get(strValue); System.out.println();
log.info("{}", String.format(ParserProcessConstant.ST.LOG_GROUP_LINE, "应用枚举映射"));
log.info("EnumMapping = {}", JSON.toJSONString(configValue.getEnumMapping()));
for(String dict : configValue.getEnumMapping().keySet()) {
if(configValue.getEnumMapping().containsKey(dict)) {
strValue = configValue.getEnumMapping().get(dict).get(strValue);
break;
}
}
} }
// 3. 应用工具函数 // 3. 应用工具函数
if (configValue.getUtilFunction() != null && !configValue.getUtilFunction().isEmpty()) { if (configValue.getUtilFunction() != null && !configValue.getUtilFunction().isEmpty()) {
System.out.println();
log.info("{}", String.format(ParserProcessConstant.ST.LOG_GROUP_LINE, "应用工具函数"));
log.info("Function = {}", JSON.toJSONString(configValue.getUtilFunction()));
strValue = applyUtilFunction(strValue, configValue.getUtilFunction(), context, loopIndex); strValue = applyUtilFunction(strValue, configValue.getUtilFunction(), context, loopIndex);
} }
@ -271,6 +292,10 @@ public class EnhancedConfigProcessor {
params.put("context", context); params.put("context", context);
params.put("loopIndex", loopIndex); params.put("loopIndex", loopIndex);
// 参数
value = params.get("params").toString();
params.remove("params");
// 调用工具函数 // 调用工具函数
result = callFormatUtilFunction(functionName, value, params); result = callFormatUtilFunction(functionName, value, params);
@ -290,7 +315,7 @@ public class EnhancedConfigProcessor {
Object result = method.invoke(null, value, params); Object result = method.invoke(null, value, params);
return result != null ? result.toString() : value; return result != null ? result.toString() : value;
} catch (Exception e) { } catch (Exception e) {
// 方法调用失败尝试其他方式 // TODO 2025-9-29 15:30:19 方法调用失败尝试其他方式
return callCustomUtilFunction(functionName, value, params); return callCustomUtilFunction(functionName, value, params);
} }
} }

View File

@ -1,19 +1,14 @@
package com.example.demo.draft.demo043.core; package com.example.demo.parser.process.core;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.example.demo.draft.demo043.domain.ConfigValue; import com.example.demo.parser.process.domain.ConfigValue;
import com.example.demo.draft.demo043.domain.LevelConfig; import com.example.demo.parser.process.domain.LevelConfig;
import com.example.demo.draft.demo043.domain.ValueConfig; import com.example.demo.parser.process.domain.ValueConfig;
import com.example.demo.draft.demo043.util.FormatUtil; import com.example.demo.parser.process.util.FormatUtil;
import com.hubspot.jinjava.Jinjava; import com.hubspot.jinjava.Jinjava;
import com.hubspot.jinjava.JinjavaConfig; import com.hubspot.jinjava.JinjavaConfig;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -51,9 +46,8 @@ import java.util.Map;
* String result2 = EnhancedTemplateGenerator.generateCode(data, "templates/custom-template.j2"); * String result2 = EnhancedTemplateGenerator.generateCode(data, "templates/custom-template.j2");
* }</pre> * }</pre>
* *
* @author Template Generator Team * @author 岳佳君 (2025年09月26日 19:57:01)
* @version 1.0.0 * @version 1.0.0
* @since 2024-01-01
* @see TemplateFileLoader * @see TemplateFileLoader
*/ */
public class EnhancedTemplateGenerator { public class EnhancedTemplateGenerator {
@ -392,7 +386,7 @@ public class EnhancedTemplateGenerator {
Object enumMappingObj = map.get("enumMapping"); Object enumMappingObj = map.get("enumMapping");
if (enumMappingObj instanceof Map) { if (enumMappingObj instanceof Map) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, String> enumMapping = (Map<String, String>) enumMappingObj; Map<String, Map<String, String>> enumMapping = (Map<String, Map<String, String>>) enumMappingObj;
builder.enumMapping(enumMapping); builder.enumMapping(enumMapping);
} }
} }

View File

@ -0,0 +1,224 @@
package com.example.demo.parser.process.core;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
/**
* 模板文件工具类
* 负责从文件系统或类路径加载模板文件支持缓存机制提高性能
*
* <p>该类提供了以下功能</p>
* <ul>
* <li>从类路径加载模板文件</li>
* <li>从文件系统加载模板文件</li>
* <li>智能识别路径前缀自动选择加载方式</li>
* <li>模板内容缓存避免重复读取文件</li>
* <li>缓存管理功能</li>
* </ul>
*
* <p>使用示例</p>
* <pre>
* // 从类路径加载
* String template1 = TemplateFileLoader.loadTemplate("classpath:templates/default.html");
* // 从文件系统加载
* String template2 = TemplateFileLoader.loadTemplate("file:/opt/templates/default.html");
* // 默认从类路径加载
* String template3 = TemplateFileLoader.loadTemplate("templates/default.html");
* </pre>
*
* @author 岳佳君 (2025年09月25日 23:42:44)
* @version 1.0.0
*/
@Slf4j
public class TemplateFileLoader {
/**
* 默认模板目录路径
*/
private static final String DEFAULT_TEMPLATE_DIR = "templates/";
/**
* 类路径前缀标识符
*/
private static final String CLASS_PATH_PREFIX = "classpath:";
/**
* 文件系统路径前缀标识符
*/
private static final String FILE_PATH_PREFIX = "file:";
/**
* 模板缓存使用HashMap存储已加载的模板内容
* Key: 缓存键包含路径前缀和模板路径
* Value: 模板文件内容
*/
private static final Map<String, String> TEMPLATE_CACHE = new HashMap<>();
/**
* 从类路径加载模板文件
*
* <p>该方法会首先检查缓存中是否已存在该模板如果存在则直接返回缓存内容
* 否则从类路径读取文件内容并存入缓存</p>
*
* @param templatePath 模板文件路径可以是相对路径或绝对路径
* 相对路径相对于类路径根目录
* @return 模板文件的内容字符串
* @throws IOException 当模板文件未找到或读取失败时抛出
* @throws IllegalArgumentException 当templatePath为null或空字符串时抛出
*/
public static String loadTemplateFromClasspath(String templatePath) throws IOException {
// 参数校验
if (templatePath == null || templatePath.trim().isEmpty()) {
throw new IllegalArgumentException("模板路径不能为空");
}
String cacheKey = CLASS_PATH_PREFIX + templatePath;
// 检查缓存中是否已存在该模板
if (TEMPLATE_CACHE.containsKey(cacheKey)) {
log.debug("从缓存加载类路径模板: {}", templatePath);
return TEMPLATE_CACHE.get(cacheKey);
}
try {
// 处理路径格式确保以"/"开头
String fullPath = templatePath.startsWith("/") ? templatePath : "/" + templatePath;
java.io.InputStream inputStream = TemplateFileLoader.class.getResourceAsStream(fullPath);
// 检查文件是否存在
if (inputStream == null) {
throw new IOException("模板文件未找到: " + templatePath);
}
// 读取文件内容并转换为字符串
String content = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
// 存入缓存
TEMPLATE_CACHE.put(cacheKey, content);
log.info("从类路径加载模板成功: {}", templatePath);
return content;
} catch (IOException e) {
log.error("从类路径加载模板失败: {}", templatePath, e);
throw e;
}
}
/**
* 从文件系统加载模板文件
*
* <p>该方法会首先检查缓存中是否已存在该模板如果存在则直接返回缓存内容
* 否则从文件系统读取文件内容并存入缓存</p>
*
* @param filePath 模板文件的绝对路径或相对路径相对于当前工作目录
* @return 模板文件的内容字符串
* @throws IOException 当模板文件不存在或读取失败时抛出
* @throws IllegalArgumentException 当filePath为null或空字符串时抛出
*/
public static String loadTemplateFromFileSystem(String filePath) throws IOException {
// 参数校验
if (filePath == null || filePath.trim().isEmpty()) {
throw new IllegalArgumentException("文件路径不能为空");
}
String cacheKey = FILE_PATH_PREFIX + filePath;
// 检查缓存中是否已存在该模板
if (TEMPLATE_CACHE.containsKey(cacheKey)) {
log.debug("从缓存加载文件系统模板: {}", filePath);
return TEMPLATE_CACHE.get(cacheKey);
}
try {
Path path = Paths.get(filePath);
// 检查文件是否存在
if (!Files.exists(path)) {
throw new IOException("模板文件不存在: " + filePath);
}
// 读取文件内容
String content = Files.readString(path, StandardCharsets.UTF_8);
// 存入缓存
TEMPLATE_CACHE.put(cacheKey, content);
log.info("从文件系统加载模板成功: {}", filePath);
return content;
} catch (IOException e) {
log.error("从文件系统加载模板失败: {}", filePath, e);
throw e;
}
}
/**
* 智能加载模板文件自动判断路径类型
*
* <p>根据路径前缀自动选择加载方式</p>
* <ul>
* <li>"classpath:"开头从类路径加载</li>
* <li>"file:"开头从文件系统加载</li>
* <li>无前缀默认从类路径加载</li>
* </ul>
*
* @param templatePath 模板路径支持带前缀的完整路径或不带前缀的相对路径
* @return 模板文件的内容字符串
* @throws IOException 当模板文件加载失败时抛出
* @throws IllegalArgumentException 当templatePath为null或空字符串时抛出
*/
public static String loadTemplate(String templatePath) throws IOException {
// 参数校验
if (templatePath == null || templatePath.trim().isEmpty()) {
throw new IllegalArgumentException("模板路径不能为空");
}
if (templatePath.startsWith(CLASS_PATH_PREFIX)) {
// 从类路径加载去掉前缀
return loadTemplateFromClasspath(templatePath.substring(CLASS_PATH_PREFIX.length()));
} else if (templatePath.startsWith(FILE_PATH_PREFIX)) {
// 从文件系统加载去掉前缀
return loadTemplateFromFileSystem(templatePath.substring(FILE_PATH_PREFIX.length()));
} else {
// 默认从类路径加载
return loadTemplateFromClasspath(templatePath);
}
}
/**
* 清除所有模板缓存
*
* <p>该方法会清空当前内存中所有的模板缓存适用于需要强制重新加载模板的场景
* 比如模板文件内容已更新但缓存还未过期的情况</p>
*/
public static void clearCache() {
int cacheSize = TEMPLATE_CACHE.size();
TEMPLATE_CACHE.clear();
log.info("模板缓存已清除,原缓存大小: {}", cacheSize);
}
/**
* 获取当前缓存中的模板数量
*
* @return 缓存中模板的数量
*/
public static int getCacheSize() {
return TEMPLATE_CACHE.size();
}
/**
* 检查指定路径的模板是否已缓存
*
* @param templatePath 模板路径需要包含完整的前缀
* @return 如果模板已缓存返回true否则返回false
*/
public static boolean isCached(String templatePath) {
return TEMPLATE_CACHE.containsKey(templatePath);
}
}

View File

@ -1,4 +1,4 @@
package com.example.demo.draft.demo043.core; package com.example.demo.parser.process.core;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -13,34 +13,87 @@ import java.util.Map;
import java.util.Stack; import java.util.Stack;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/**
* XML转AFSIM格式转换器
*
* <p>该类提供将XML文件转换为JSON格式并应用正则表达式规则进行键名转换的功能
* 采用流式处理方式适用于处理大型XML文件避免内存溢出</p>
*
* <p>主要功能</p>
* <ul>
* <li>流式解析XML文件降低内存占用</li>
* <li>支持正则表达式规则对JSON键名进行转换</li>
* <li>自动处理XML属性和元素内容</li>
* <li>生成标准JSON数组格式输出</li>
* </ul>
*
* @author 岳佳君 (2025年09月25日 23:42:44)
* @version 1.0.0
*/
@Slf4j @Slf4j
public class Xml2AFSIMTransformation { public class Xml2AFSIMTransformation {
/**
* 正则表达式规则映射
* Key: 编译后的正则表达式模式
* Value: 替换字符串
*/
private final Map<Pattern, String> regexRules; private final Map<Pattern, String> regexRules;
/**
* 构造函数初始化转换规则
*
* @param rules 转换规则映射Key为匹配的正则表达式Value为替换字符串
* 如果为null则使用空规则集
*/
public Xml2AFSIMTransformation(Map<String, String> rules) { public Xml2AFSIMTransformation(Map<String, String> rules) {
log.info("初始化转换器,规则数量: {}", rules != null ? rules.size() : 0); log.info("初始化XML转AFSIM转换器,规则数量: {}", rules != null ? rules.size() : 0);
// 编译正则表达式规则 // 编译正则表达式规则
regexRules = new HashMap<>(); regexRules = new HashMap<>();
if (rules != null) { if (rules != null) {
for (Map.Entry<String, String> entry : rules.entrySet()) { for (Map.Entry<String, String> entry : rules.entrySet()) {
// 预编译正则表达式以提高性能
regexRules.put(Pattern.compile(entry.getKey()), entry.getValue()); regexRules.put(Pattern.compile(entry.getKey()), entry.getValue());
} }
} }
log.debug("正则表达式规则编译完成");
} }
/** /**
* 流式XML转JSON并应用转换规则 * 将XML文件转换为JSON格式并应用转换规则
*
* <p>该方法使用StAX流式API解析XML适用于处理大型文件
* 转换后的JSON格式为对象数组每个XML根元素对应一个JSON对象</p>
*
* @param xmlFile 输入的XML文件不能为null
* @param jsonFile 输出的JSON文件不能为null
* @param rootElement 根元素名称用于标识每个JSON对象的开始和结束
* @throws Exception 当文件读写失败XML解析错误或转换过程中出现异常时抛出
* @throws IllegalArgumentException 当参数为null或空字符串时抛出
*/ */
public void convertXmlToJson(File xmlFile, File jsonFile, String rootElement) throws Exception { public void convertXmlToJson(File xmlFile, File jsonFile, String rootElement) throws Exception {
// 参数校验
if (xmlFile == null || !xmlFile.exists()) {
throw new IllegalArgumentException("XML文件不存在或为null: " + xmlFile);
}
if (jsonFile == null) {
throw new IllegalArgumentException("JSON文件路径不能为null");
}
if (rootElement == null || rootElement.trim().isEmpty()) {
throw new IllegalArgumentException("根元素名称不能为空");
}
log.info("开始XML转JSON转换并应用规则"); log.info("开始XML转JSON转换并应用规则");
log.debug("输入文件: {}, 输出文件: {}, 根元素: {}", xmlFile.getPath(), jsonFile.getPath(), rootElement);
try (FileInputStream xmlInputStream = new FileInputStream(xmlFile); try (FileInputStream xmlInputStream = new FileInputStream(xmlFile);
FileWriter jsonWriter = new FileWriter(jsonFile)) { FileWriter jsonWriter = new FileWriter(jsonFile)) {
// 创建XML流读取器
XMLInputFactory factory = XMLInputFactory.newInstance(); XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(xmlInputStream); XMLStreamReader reader = factory.createXMLStreamReader(xmlInputStream);
// 写入JSON数组开始标记
jsonWriter.write("[\n"); jsonWriter.write("[\n");
boolean firstObject = true; boolean firstObject = true;
@ -52,6 +105,7 @@ public class Xml2AFSIMTransformation {
StringBuilder currentText = new StringBuilder(); StringBuilder currentText = new StringBuilder();
String currentElement = null; String currentElement = null;
// 流式解析XML
while (reader.hasNext()) { while (reader.hasNext()) {
int event = reader.next(); int event = reader.next();
@ -80,7 +134,7 @@ public class Xml2AFSIMTransformation {
String text = reader.getText().trim(); String text = reader.getText().trim();
if (!text.isEmpty()) { if (!text.isEmpty()) {
currentText.append(text); currentText.append(text);
log.debug("文本内容: {}", text); log.trace("文本内容: {}", text);
} }
} }
break; break;
@ -112,6 +166,7 @@ public class Xml2AFSIMTransformation {
jsonWriter.write(json); jsonWriter.write(json);
objectCount++; objectCount++;
// 每处理100个对象刷新一次缓冲区并记录日志
if (objectCount % 100 == 0) { if (objectCount % 100 == 0) {
log.info("已处理 {} 个对象", objectCount); log.info("已处理 {} 个对象", objectCount);
jsonWriter.flush(); jsonWriter.flush();
@ -125,48 +180,68 @@ public class Xml2AFSIMTransformation {
} }
} }
// 写入JSON数组结束标记
jsonWriter.write("\n]"); jsonWriter.write("\n]");
log.info("转换完成,共处理 {} 个对象", objectCount); log.info("转换完成,共处理 {} 个对象", objectCount);
} catch (Exception e) { } catch (Exception e) {
log.error("转换失败", e); log.error("XML转JSON转换失败,文件: {}", xmlFile.getPath(), e);
throw e; throw e;
} }
} }
/** /**
* 处理元素的属性 * 处理XML元素的属性
*
* <p>将元素的属性添加到当前对象中属性键名为"元素名@属性名"格式</p>
*
* @param reader XML流读取器
* @param elementStack 元素栈用于跟踪当前解析路径
* @param currentObject 当前正在构建的对象
*/ */
private void processAttributesForElement(XMLStreamReader reader, Stack<String> elementStack, private void processAttributesForElement(XMLStreamReader reader, Stack<String> elementStack,
Map<String, Object> currentObject) { Map<String, Object> currentObject) {
if (reader.getAttributeCount() > 0) { int attributeCount = reader.getAttributeCount();
for (int i = 0; i < reader.getAttributeCount(); i++) { if (attributeCount > 0) {
log.debug("处理元素 {} 的属性,属性数量: {}", elementStack.peek(), attributeCount);
for (int i = 0; i < attributeCount; i++) {
String attrName = reader.getAttributeLocalName(i); String attrName = reader.getAttributeLocalName(i);
String attrValue = reader.getAttributeValue(i); String attrValue = reader.getAttributeValue(i);
// 默认处理将属性添加到对象中 // 将属性添加到对象中格式为元素名@属性名
String attrKey = elementStack.peek() + "@" + attrName; String attrKey = elementStack.peek() + "@" + attrName;
currentObject.put(attrKey, attrValue); currentObject.put(attrKey, attrValue);
log.trace("添加属性: {} = {}", attrKey, attrValue);
} }
} }
} }
/** /**
* 处理元素文本内容 * 处理XML元素的文本内容
*
* <p>将元素的文本内容添加到当前对象中键名为完整的元素路径</p>
*
* @param elementName 元素名称
* @param content 元素文本内容
* @param elementStack 元素栈用于构建完整路径
* @param currentObject 当前正在构建的对象
*/ */
private void processElementContent(String elementName, String content, private void processElementContent(String elementName, String content,
Stack<String> elementStack, Map<String, Object> currentObject) { Stack<String> elementStack, Map<String, Object> currentObject) {
// 默认处理将元素内容添加到对象中 // 构建完整的元素路径作为key父元素.当前元素
// 构建完整的元素路径作为key
String elementKey = String.join(".", elementStack) + "." + elementName; String elementKey = String.join(".", elementStack) + "." + elementName;
currentObject.put(elementKey, content); currentObject.put(elementKey, content);
log.debug("添加元素内容: {} = {}", elementKey, content);
} }
/** /**
* 将对象转换为JSON字符串 * 将Map对象转换为JSON字符串
*
* @param object 要转换的对象映射
* @return JSON格式的字符串如果对象为空则返回null
*/ */
private String convertObjectToJson(Map<String, Object> object) { private String convertObjectToJson(Map<String, Object> object) {
if (object.isEmpty()) { if (object == null || object.isEmpty()) {
log.warn("空对象,跳过输出"); log.warn("空对象,跳过JSON转换");
return null; return null;
} }
@ -174,12 +249,15 @@ public class Xml2AFSIMTransformation {
return mapToJson(object); return mapToJson(object);
} catch (Exception e) { } catch (Exception e) {
log.error("对象转JSON失败", e); log.error("对象转JSON失败", e);
return "{}"; return "{}"; // 返回空对象作为容错处理
} }
} }
/** /**
* Map转JSON字符串 * 递归将Map转换为JSON字符串
*
* @param map 要转换的映射
* @return JSON对象字符串
*/ */
private String mapToJson(Map<String, Object> map) { private String mapToJson(Map<String, Object> map) {
if (map.isEmpty()) { if (map.isEmpty()) {
@ -204,7 +282,10 @@ public class Xml2AFSIMTransformation {
} }
/** /**
* 值转JSON * 将值转换为JSON格式
*
* @param value 要转换的值支持StringNumberBooleanMapList等类型
* @return JSON格式的值表示
*/ */
private String valueToJson(Object value) { private String valueToJson(Object value) {
if (value == null) { if (value == null) {
@ -239,14 +320,21 @@ public class Xml2AFSIMTransformation {
return json.toString(); return json.toString();
} }
// 默认处理转换为字符串
return "\"" + escapeJson(value.toString()) + "\""; return "\"" + escapeJson(value.toString()) + "\"";
} }
/** /**
* JSON特殊字符转义 * JSON字符串转义处理
*
* <p>转义JSON中的特殊字符包括引号反斜杠控制字符等</p>
*
* @param text 要转义的文本
* @return 转义后的安全JSON字符串
*/ */
private String escapeJson(String text) { private String escapeJson(String text) {
if (text == null) return ""; if (text == null) return "";
return text.replace("\\", "\\\\") return text.replace("\\", "\\\\")
.replace("\"", "\\\"") .replace("\"", "\\\"")
.replace("\b", "\\b") .replace("\b", "\\b")
@ -258,6 +346,11 @@ public class Xml2AFSIMTransformation {
/** /**
* 应用正则表达式转换规则到单个对象 * 应用正则表达式转换规则到单个对象
*
* <p>遍历对象的所有键对每个键应用正则表达式规则进行转换</p>
*
* @param originalMap 原始对象映射
* @return 应用规则转换后的新对象映射
*/ */
private Map<String, Object> applyRules(Map<String, Object> originalMap) { private Map<String, Object> applyRules(Map<String, Object> originalMap) {
Map<String, Object> transformedMap = new HashMap<>(); Map<String, Object> transformedMap = new HashMap<>();
@ -270,25 +363,32 @@ public class Xml2AFSIMTransformation {
// 如果找到匹配的规则则使用新key否则保留原key // 如果找到匹配的规则则使用新key否则保留原key
if (newKey != null) { if (newKey != null) {
transformedMap.put(newKey, value); transformedMap.put(newKey, value);
log.debug("转换: {} -> {}", originalKey, newKey); log.debug("键名转换: {} -> {}", originalKey, newKey);
} else { } else {
transformedMap.put(originalKey, value); transformedMap.put(originalKey, value);
} }
} }
log.debug("规则应用完成,原始键数: {}, 转换后键数: {}", originalMap.size(), transformedMap.size());
return transformedMap; return transformedMap;
} }
/** /**
* 查找并替换匹配的正则规则 * 查找并替换匹配的正则规则
*
* <p>遍历所有正则规则找到第一个匹配的规则并进行替换</p>
*
* @param originalKey 原始键名
* @return 替换后的新键名如果没有匹配规则则返回null
*/ */
private String findAndReplace(String originalKey) { private String findAndReplace(String originalKey) {
for (Map.Entry<Pattern, String> rule : regexRules.entrySet()) { for (Map.Entry<Pattern, String> rule : regexRules.entrySet()) {
if (rule.getKey().matcher(originalKey).matches()) { if (rule.getKey().matcher(originalKey).matches()) {
return rule.getKey().matcher(originalKey).replaceAll(rule.getValue()); String newKey = rule.getKey().matcher(originalKey).replaceAll(rule.getValue());
log.trace("正则匹配: {} -> {} (规则: {})", originalKey, newKey, rule.getKey().pattern());
return newKey;
} }
} }
return null; return null;
} }
} }

View File

@ -1,4 +1,4 @@
package com.example.demo.draft.demo043.domain; package com.example.demo.parser.process.domain;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
@ -33,9 +33,8 @@ import java.util.Map;
* } * }
* </pre> * </pre>
* *
* @author Generated * @author 岳佳君 (2025年09月25日 23:42:44)
* @version 1.0 * @version 1.0.0
* @since 2024
*/ */
@Data @Data
@Builder @Builder

Some files were not shown because too many files have changed in this diff Show More