Compare commits

..

10 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
71 changed files with 4989 additions and 60 deletions

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

@ -58,7 +58,7 @@ public class BaseDTO implements Serializable {
*/
@Column(isLogicDelete = true)
@Schema(description = "是否删除")
private String isDelete;
private Integer isDelete;
/**
* 乐观锁版本号
@ -68,29 +68,6 @@ public class BaseDTO implements Serializable {
private Integer revision;
// 创建时间创建ID更新时间更新ID不允许前端或API直接控制
// /**
// * 创建时间
// */
// @Schema(description = "创建时间")
// private Date createdTime;
//
// /**
// * 创建人ID
// */
// @Schema(description = "创建人ID")
// private String createdId;
//
// /**
// * 更新时间
// */
// @Schema(description = "更新时间")
// private Date updatedTime;
//
// /**
// * 更新人ID
// */
// @Schema(description = "更新人ID")
// private String updatedId;
/**
* 租户ID

View File

@ -75,7 +75,7 @@ public class BaseEntity implements Serializable {
*/
@Column(isLogicDelete = true)
@Schema(description = "是否已删除")
private String isDeleted;
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

@ -1,11 +1,226 @@
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 基础接口包含通用的CRUD操作
*
* @param <VO> 视图对象类型
* @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,8 +6,10 @@ import com.example.demo.common.domain.BaseEntity;
import com.example.demo.common.domain.BaseQueryDTO;
import com.example.demo.common.domain.BaseVO;
import com.mybatisflex.core.service.IService;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
/**
* 统一 Service 接口
@ -60,9 +62,40 @@ public interface BaseService<Entity extends BaseEntity, VO extends BaseVO, DTO e
*/
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();
/**
* 导入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.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.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.SearchResult;
import cn.zhxu.bs.operator.Contain;
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.domain.BaseDTO;
import com.example.demo.common.domain.BaseEntity;
import com.example.demo.common.domain.BaseQueryDTO;
import com.example.demo.common.domain.BaseVO;
import com.example.demo.common.domain.*;
import com.example.demo.common.exception.BusinessException;
import com.fhs.trans.service.impl.TransService;
import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.springframework.beans.factory.DisposableBean;
@ -24,10 +32,12 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.nio.charset.StandardCharsets;
import java.util.*;
/**
* 统一 Service 实现类
@ -59,6 +69,9 @@ public abstract class BaseServiceImpl<
/** 实际业务实现VO类 */
private final Class<VO> clazzVO;
/** 实际业务实现Entity类 */
private final Class<Entity> clazzEntity;
/** 提供Select服务 */
private final BeanSearcher beanSearcher;
@ -164,12 +177,187 @@ public abstract class BaseServiceImpl<
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
public void refreshCache() {
// ignore
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
public void init() {
// ignore
@ -270,4 +458,29 @@ public abstract class BaseServiceImpl<
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,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

@ -14,7 +14,7 @@ public class WrapMapper {
*
* @return 响应结果
*/
public static Wrapper<Object> ok() {
public static <ResponseData> Wrapper<ResponseData> ok() {
return ok(null, "操作成功");
}
@ -34,7 +34,7 @@ public class WrapMapper {
* @param data 响应数据
* @return 响应结果
*/
public static <T> Wrapper<T> ok(T data) {
public static <ResponseData> Wrapper<ResponseData> ok(ResponseData data) {
return ok(data, "操作成功");
}
@ -45,8 +45,8 @@ public class WrapMapper {
* @param message 响应消息
* @return 响应结果
*/
public static <T> Wrapper<T> ok(T data, String message) {
Wrapper<T> result = new Wrapper<>();
public static <ResponseData> Wrapper<ResponseData> ok(ResponseData data, String message) {
Wrapper<ResponseData> result = new Wrapper<>();
result.setCode("SUCCESS");
result.setMessage(message);
result.setData(data);
@ -54,12 +54,31 @@ public class WrapMapper {
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 响应结果
*/
public static <T> Wrapper<T> fail() {
public static <ResponseData> Wrapper<ResponseData> fail() {
return fail("FAIL", "操作失败");
}
@ -69,7 +88,7 @@ public class WrapMapper {
* @param message 响应消息
* @return 响应结果
*/
public static <T> Wrapper<T> fail(String message) {
public static <ResponseData> Wrapper<ResponseData> fail(String message) {
return fail("FAIL", message);
}
@ -80,8 +99,8 @@ public class WrapMapper {
* @param message 响应消息
* @return 响应结果
*/
public static <T> Wrapper<T> fail(String code, String message) {
Wrapper<T> result = new Wrapper<>();
public static <ResponseData> Wrapper<ResponseData> fail(String code, String message) {
Wrapper<ResponseData> result = new Wrapper<>();
result.setCode(code);
result.setMessage(message);
result.setTimestamp(System.currentTimeMillis());

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

@ -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

@ -6,13 +6,16 @@ import com.example.demo.common.wrapper.Wrapper;
import com.example.demo.common.exception.BusinessException;
import com.example.demo.parser.model.dto.MapperRuleDTO;
import com.example.demo.parser.model.dto.MapperRuleQueryDTO;
import com.example.demo.parser.model.vo.MapperRuleNoWithNullVO;
import com.example.demo.parser.model.vo.MapperRuleVO;
import com.example.demo.parser.model.vo.ParseRuleNoWithNullVO;
import com.example.demo.parser.service.MapperRuleService;
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.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@ -46,7 +49,9 @@ public class MapperRuleController {
@RequestBody MapperRuleDTO rule) {
try {
MapperRuleVO result = mapperRuleService.create(rule);
return WrapMapper.ok(result, "映射规则创建成功");
MapperRuleNoWithNullVO vo = new MapperRuleNoWithNullVO();
BeanUtils.copyProperties(result, vo);
return WrapMapper.ok(vo, "映射规则创建成功");
} catch (BusinessException e) {
log.error("映射规则创建失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());

View File

@ -6,6 +6,7 @@ import com.example.demo.common.wrapper.Wrapper;
import com.example.demo.common.exception.BusinessException;
import com.example.demo.parser.model.dto.ParseRuleDTO;
import com.example.demo.parser.model.dto.ParseRuleQueryDTO;
import com.example.demo.parser.model.vo.ParseRuleNoWithNullVO;
import com.example.demo.parser.model.vo.ParseRuleVO;
import com.example.demo.parser.service.ParseRuleService;
import io.swagger.v3.oas.annotations.Operation;
@ -13,6 +14,7 @@ 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.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@ -41,12 +43,14 @@ public class ParseRuleController {
*/
@PostMapping
@Operation(summary = "创建解析规则", description = "创建新的解析规则")
public Wrapper<ParseRuleVO> createRule(
public Wrapper<ParseRuleNoWithNullVO> createRule(
@Parameter(description = "解析规则数据", required = true)
@RequestBody ParseRuleDTO rule) {
try {
ParseRuleVO result = parseRuleService.create(rule);
return WrapMapper.ok(result, "解析规则创建成功");
ParseRuleNoWithNullVO vo = new ParseRuleNoWithNullVO();
BeanUtils.copyProperties(result, vo);
return WrapMapper.ok(vo, "解析规则创建成功");
} catch (BusinessException e) {
log.error("解析规则创建失败: {}", e.getMessage(), e);
return WrapMapper.fail(e.getMessage());

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

@ -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

@ -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

@ -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

@ -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

@ -28,7 +28,7 @@ import java.util.Date;
@Accessors(chain=true)
@NoArgsConstructor
@AllArgsConstructor
public class FileRecordDTO extends BaseDTO implements Serializable {
public class FileRecordDTO extends BaseDTO {
@Serial
private static final long serialVersionUID = 1L;

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

@ -27,7 +27,7 @@ import java.io.Serializable;
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class MapperRuleDTO extends BaseDTO implements Serializable {
public class MapperRuleDTO extends BaseDTO {
@Serial
private static final long serialVersionUID = 1L;
@ -67,4 +67,11 @@ public class MapperRuleDTO extends BaseDTO implements Serializable {
@NotNull(message = "排序顺序不能为空")
@Schema(description = "排序顺序")
private Integer sortOrder;
/**
* 映射类型
*/
@Size(max = 50, message = "映射类型不能超过50个字符")
@Schema(description = "映射类型")
private String mappingType;
}

View File

@ -25,7 +25,7 @@ import java.io.Serializable;
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class MapperRuleQueryDTO extends BaseQueryDTO implements Serializable {
public class MapperRuleQueryDTO extends BaseQueryDTO {
@Serial
private static final long serialVersionUID = 1L;

View File

@ -26,7 +26,7 @@ import java.io.Serializable;
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ParseRuleDTO extends BaseDTO implements Serializable {
public class ParseRuleDTO extends BaseDTO {
@Serial
private static final long serialVersionUID = 1L;
@ -60,4 +60,11 @@ public class ParseRuleDTO extends BaseDTO implements Serializable {
@Size(max = 255, message = "节点路径不能超过255个字符")
@Schema(description = "节点路径")
private String nodePath;
/**
* TXT文件中的键名
*/
@Size(max = 100, message = "TXT文件中的键名不能超过100个字符")
@Schema(description = "TXT文件中的键名")
private String txtKey;
}

View File

@ -25,7 +25,7 @@ import java.io.Serializable;
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ParseRuleQueryDTO extends BaseQueryDTO implements Serializable {
public class ParseRuleQueryDTO extends BaseQueryDTO {
@Serial
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

@ -30,7 +30,7 @@ import java.util.Date;
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SearchBean(
tables = "file_record",
tables = "file_record a",
autoMapTo = "a"
)
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

@ -27,7 +27,7 @@ import java.io.Serializable;
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SearchBean(
tables = "mapper_rule",
tables = "mapper_rule a",
autoMapTo = "a"
)
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

@ -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,19 @@
package com.example.demo.parser.service;
import com.example.demo.common.typography.BaseService;
import com.example.demo.parser.entity.ConditionMapEntity;
import com.example.demo.parser.model.dto.ConditionMapDTO;
import com.example.demo.parser.model.dto.ConditionMapQueryDTO;
import com.example.demo.parser.model.vo.ConditionMapVO;
/**
* 条件类型映射服务接口
* 提供条件类型映射的CRUD及其他业务操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @since 1.0.0
* @version 1.0.0
*/
public interface ConditionMapService
extends BaseService<ConditionMapEntity, ConditionMapVO, ConditionMapDTO, ConditionMapQueryDTO> {
}

View File

@ -0,0 +1,19 @@
package com.example.demo.parser.service;
import com.example.demo.common.typography.BaseService;
import com.example.demo.parser.entity.ConfigDocumentEntity;
import com.example.demo.parser.model.dto.ConfigDocumentDTO;
import com.example.demo.parser.model.dto.ConfigDocumentQueryDTO;
import com.example.demo.parser.model.vo.ConfigDocumentVO;
/**
* 配置文档服务接口
* 提供配置文档的CRUD及其他业务操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @since 1.0.0
* @version 1.0.0
*/
public interface ConfigDocumentService
extends BaseService<ConfigDocumentEntity, ConfigDocumentVO, ConfigDocumentDTO, ConfigDocumentQueryDTO> {
}

View File

@ -0,0 +1,19 @@
package com.example.demo.parser.service;
import com.example.demo.common.typography.BaseService;
import com.example.demo.parser.entity.ConfigValueEntity;
import com.example.demo.parser.model.dto.ConfigValueDTO;
import com.example.demo.parser.model.dto.ConfigValueQueryDTO;
import com.example.demo.parser.model.vo.ConfigValueVO;
/**
* 配置值服务接口
* 提供配置值的CRUD及其他业务操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @since 1.0.0
* @version 1.0.0
*/
public interface ConfigValueService
extends BaseService<ConfigValueEntity, ConfigValueVO, ConfigValueDTO, ConfigValueQueryDTO> {
}

View File

@ -0,0 +1,19 @@
package com.example.demo.parser.service;
import com.example.demo.common.typography.BaseService;
import com.example.demo.parser.entity.LevelConfigEntity;
import com.example.demo.parser.model.dto.LevelConfigDTO;
import com.example.demo.parser.model.dto.LevelConfigQueryDTO;
import com.example.demo.parser.model.vo.LevelConfigVO;
/**
* 层级配置服务接口
* 提供层级配置的CRUD及其他业务操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @since 1.0.0
* @version 1.0.0
*/
public interface LevelConfigService
extends BaseService<LevelConfigEntity, LevelConfigVO, LevelConfigDTO, LevelConfigQueryDTO> {
}

View File

@ -0,0 +1,19 @@
package com.example.demo.parser.service;
import com.example.demo.common.typography.BaseService;
import com.example.demo.parser.entity.ValueConfigEntity;
import com.example.demo.parser.model.dto.ValueConfigDTO;
import com.example.demo.parser.model.dto.ValueConfigQueryDTO;
import com.example.demo.parser.model.vo.ValueConfigVO;
/**
* 值配置服务接口
* 提供值配置的CRUD及其他业务操作
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @since 1.0.0
* @version 1.0.0
*/
public interface ValueConfigService
extends BaseService<ValueConfigEntity, ValueConfigVO, ValueConfigDTO, ValueConfigQueryDTO> {
}

View File

@ -0,0 +1,167 @@
package com.example.demo.parser.service;
import com.example.demo.parser.model.dto.ParseRuleDTO;
import com.example.demo.parser.model.dto.MapperRuleDTO;
import java.util.List;
import java.util.Map;
/**
* XML解析服务接口
* 提供XML文件解析和转换的核心功能
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
public interface XmlParserService {
/**
* 解析XML文件并转换为TXT格式
*
* @param xmlFilePath XML文件路径
* @param txtFilePath TXT文件输出路径
* @param parseRules 解析规则列表
* @param mapperRules 映射规则列表
* @return 解析结果信息
*/
ParseResult parseXmlToTxt(String xmlFilePath, String txtFilePath,
List<ParseRuleDTO> parseRules, List<MapperRuleDTO> mapperRules);
/**
* 解析XML文件并转换为TXT格式使用默认规则
*
* @param xmlFilePath XML文件路径
* @param txtFilePath TXT文件输出路径
* @return 解析结果信息
*/
ParseResult parseXmlToTxt(String xmlFilePath, String txtFilePath);
/**
* 验证XML文件格式
*
* @param xmlFilePath XML文件路径
* @return 验证结果
*/
ValidationResult validateXmlFile(String xmlFilePath);
/**
* 获取XML文件结构信息
*
* @param xmlFilePath XML文件路径
* @return 结构信息
*/
XmlStructureInfo getXmlStructure(String xmlFilePath);
/**
* 解析结果类
*/
class ParseResult {
private boolean success;
private String message;
private String outputPath;
private int elementCount;
private Map<String, Object> statistics;
public ParseResult(boolean success, String message) {
this.success = success;
this.message = message;
}
public ParseResult(boolean success, String message, String outputPath,
int elementCount, Map<String, Object> statistics) {
this.success = success;
this.message = message;
this.outputPath = outputPath;
this.elementCount = elementCount;
this.statistics = statistics;
}
// Getters and Setters
public boolean isSuccess() { return success; }
public void setSuccess(boolean success) { this.success = success; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public String getOutputPath() { return outputPath; }
public void setOutputPath(String outputPath) { this.outputPath = outputPath; }
public int getElementCount() { return elementCount; }
public void setElementCount(int elementCount) { this.elementCount = elementCount; }
public Map<String, Object> getStatistics() { return statistics; }
public void setStatistics(Map<String, Object> statistics) { this.statistics = statistics; }
}
/**
* 验证结果类
*/
class ValidationResult {
private boolean valid;
private String message;
private List<String> errors;
public ValidationResult(boolean valid, String message) {
this.valid = valid;
this.message = message;
}
public ValidationResult(boolean valid, String message, List<String> errors) {
this.valid = valid;
this.message = message;
this.errors = errors;
}
// Getters and Setters
public boolean isValid() { return valid; }
public void setValid(boolean valid) { this.valid = valid; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public List<String> getErrors() { return errors; }
public void setErrors(List<String> errors) { this.errors = errors; }
}
/**
* XML结构信息类
*/
class XmlStructureInfo {
private String rootElement;
private int totalElements;
private int totalAttributes;
private List<String> elementNames;
private Map<String, Integer> elementCounts;
private List<String> attributeNames;
public XmlStructureInfo(String rootElement, int totalElements, int totalAttributes,
List<String> elementNames, Map<String, Integer> elementCounts,
List<String> attributeNames) {
this.rootElement = rootElement;
this.totalElements = totalElements;
this.totalAttributes = totalAttributes;
this.elementNames = elementNames;
this.elementCounts = elementCounts;
this.attributeNames = attributeNames;
}
// Getters and Setters
public String getRootElement() { return rootElement; }
public void setRootElement(String rootElement) { this.rootElement = rootElement; }
public int getTotalElements() { return totalElements; }
public void setTotalElements(int totalElements) { this.totalElements = totalElements; }
public int getTotalAttributes() { return totalAttributes; }
public void setTotalAttributes(int totalAttributes) { this.totalAttributes = totalAttributes; }
public List<String> getElementNames() { return elementNames; }
public void setElementNames(List<String> elementNames) { this.elementNames = elementNames; }
public Map<String, Integer> getElementCounts() { return elementCounts; }
public void setElementCounts(Map<String, Integer> elementCounts) { this.elementCounts = elementCounts; }
public List<String> getAttributeNames() { return attributeNames; }
public void setAttributeNames(List<String> attributeNames) { this.attributeNames = attributeNames; }
}
}

View File

@ -0,0 +1,47 @@
package com.example.demo.parser.service.impl;
import cn.zhxu.bs.BeanSearcher;
import com.example.demo.common.typography.BaseServiceImpl;
import com.example.demo.parser.entity.ConditionMapEntity;
import com.example.demo.parser.mapper.ConditionMapMapper;
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 com.fhs.trans.service.impl.TransService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 条件类型映射服务实现类
* 提供条件类型映射的CRUD和查询功能继承BaseServiceImpl实现基础功能
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class ConditionMapServiceImpl
extends BaseServiceImpl<ConditionMapEntity, ConditionMapVO, ConditionMapDTO, ConditionMapQueryDTO, ConditionMapMapper>
implements ConditionMapService {
/**
* 构造函数
*
* @param beanSearcher BeanSearcher实例用于高级查询
* @param transService 翻译服务实例用于字段翻译
*/
public ConditionMapServiceImpl(
BeanSearcher beanSearcher,
TransService transService
) {
super(log,
ConditionMapServiceImpl.class.getSimpleName(),
ConditionMapVO.class,
ConditionMapEntity.class,
beanSearcher, transService);
}
}

View File

@ -0,0 +1,47 @@
package com.example.demo.parser.service.impl;
import cn.zhxu.bs.BeanSearcher;
import com.example.demo.common.typography.BaseServiceImpl;
import com.example.demo.parser.entity.ConfigDocumentEntity;
import com.example.demo.parser.mapper.ConfigDocumentMapper;
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 com.fhs.trans.service.impl.TransService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 配置文档服务实现类
* 提供配置文档的CRUD和查询功能继承BaseServiceImpl实现基础功能
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class ConfigDocumentServiceImpl
extends BaseServiceImpl<ConfigDocumentEntity, ConfigDocumentVO, ConfigDocumentDTO, ConfigDocumentQueryDTO, ConfigDocumentMapper>
implements ConfigDocumentService {
/**
* 构造函数
*
* @param beanSearcher BeanSearcher实例用于高级查询
* @param transService 翻译服务实例用于字段翻译
*/
public ConfigDocumentServiceImpl(
BeanSearcher beanSearcher,
TransService transService
) {
super(log,
ConfigDocumentServiceImpl.class.getSimpleName(),
ConfigDocumentVO.class,
ConfigDocumentEntity.class,
beanSearcher, transService);
}
}

View File

@ -0,0 +1,47 @@
package com.example.demo.parser.service.impl;
import cn.zhxu.bs.BeanSearcher;
import com.example.demo.common.typography.BaseServiceImpl;
import com.example.demo.parser.entity.ConfigValueEntity;
import com.example.demo.parser.mapper.ConfigValueMapper;
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 com.fhs.trans.service.impl.TransService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 配置值服务实现类
* 提供配置值的CRUD和查询功能继承BaseServiceImpl实现基础功能
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class ConfigValueServiceImpl
extends BaseServiceImpl<ConfigValueEntity, ConfigValueVO, ConfigValueDTO, ConfigValueQueryDTO, ConfigValueMapper>
implements ConfigValueService {
/**
* 构造函数
*
* @param beanSearcher BeanSearcher实例用于高级查询
* @param transService 翻译服务实例用于字段翻译
*/
public ConfigValueServiceImpl(
BeanSearcher beanSearcher,
TransService transService
) {
super(log,
ConfigValueServiceImpl.class.getSimpleName(),
ConfigValueVO.class,
ConfigValueEntity.class,
beanSearcher, transService);
}
}

View File

@ -37,6 +37,10 @@ public class FileRecordServiceImpl
BeanSearcher beanSearcher,
TransService transService
) {
super(log, FileRecordServiceImpl.class.getSimpleName(), FileRecordVO.class, beanSearcher, transService);
super(log,
FileRecordServiceImpl.class.getSimpleName(),
FileRecordVO.class,
FileRecordEntity.class,
beanSearcher, transService);
}
}

View File

@ -0,0 +1,47 @@
package com.example.demo.parser.service.impl;
import cn.zhxu.bs.BeanSearcher;
import com.example.demo.common.typography.BaseServiceImpl;
import com.example.demo.parser.entity.LevelConfigEntity;
import com.example.demo.parser.mapper.LevelConfigMapper;
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 com.fhs.trans.service.impl.TransService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 层级配置服务实现类
* 提供层级配置的CRUD和查询功能继承BaseServiceImpl实现基础功能
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class LevelConfigServiceImpl
extends BaseServiceImpl<LevelConfigEntity, LevelConfigVO, LevelConfigDTO, LevelConfigQueryDTO, LevelConfigMapper>
implements LevelConfigService {
/**
* 构造函数
*
* @param beanSearcher BeanSearcher实例用于高级查询
* @param transService 翻译服务实例用于字段翻译
*/
public LevelConfigServiceImpl(
BeanSearcher beanSearcher,
TransService transService
) {
super(log,
LevelConfigServiceImpl.class.getSimpleName(),
LevelConfigVO.class,
LevelConfigEntity.class,
beanSearcher, transService);
}
}

View File

@ -38,7 +38,11 @@ public class MapperRuleServiceImpl
BeanSearcher beanSearcher,
TransService transService
) {
super(log, MapperRuleServiceImpl.class.getSimpleName(), MapperRuleVO.class, beanSearcher, transService);
super(log,
MapperRuleServiceImpl.class.getSimpleName(),
MapperRuleVO.class,
MapperRuleEntity.class,
beanSearcher, transService);
}
}

View File

@ -38,7 +38,11 @@ public class ParseRuleServiceImpl
BeanSearcher beanSearcher,
TransService transService
) {
super(log, ParseRuleServiceImpl.class.getSimpleName(), ParseRuleVO.class, beanSearcher, transService);
super(log,
ParseRuleServiceImpl.class.getSimpleName(),
ParseRuleVO.class,
ParseRuleEntity.class,
beanSearcher, transService);
}
}

View File

@ -0,0 +1,47 @@
package com.example.demo.parser.service.impl;
import cn.zhxu.bs.BeanSearcher;
import com.example.demo.common.typography.BaseServiceImpl;
import com.example.demo.parser.entity.ValueConfigEntity;
import com.example.demo.parser.mapper.ValueConfigMapper;
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 com.fhs.trans.service.impl.TransService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 值配置服务实现类
* 提供值配置的CRUD和查询功能继承BaseServiceImpl实现基础功能
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class ValueConfigServiceImpl
extends BaseServiceImpl<ValueConfigEntity, ValueConfigVO, ValueConfigDTO, ValueConfigQueryDTO, ValueConfigMapper>
implements ValueConfigService {
/**
* 构造函数
*
* @param beanSearcher BeanSearcher实例用于高级查询
* @param transService 翻译服务实例用于字段翻译
*/
public ValueConfigServiceImpl(
BeanSearcher beanSearcher,
TransService transService
) {
super(log,
ValueConfigServiceImpl.class.getSimpleName(),
ValueConfigVO.class,
ValueConfigEntity.class,
beanSearcher, transService);
}
}

View File

@ -0,0 +1,427 @@
package com.example.demo.parser.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import com.example.demo.common.constant.GlobalConstants;
import com.example.demo.parser.model.dto.MapperRuleDTO;
import com.example.demo.parser.model.dto.ParseRuleDTO;
import com.example.demo.parser.service.XmlParserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
/**
* XML解析服务实现类
* 提供XML文件解析和转换的核心功能实现
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Slf4j
@Service
public class XmlParserServiceImpl implements XmlParserService {
/**
* 解析XML文件并转换为TXT格式
*
* @param xmlFilePath XML文件路径
* @param txtFilePath TXT文件输出路径
* @param parseRules 解析规则列表
* @param mapperRules 映射规则列表
* @return 解析结果信息
*/
@Override
public ParseResult parseXmlToTxt(String xmlFilePath, String txtFilePath,
List<ParseRuleDTO> parseRules, List<MapperRuleDTO> mapperRules) {
try {
log.info("开始解析XML文件: {}", xmlFilePath);
// 验证文件存在性
if (!FileUtil.exist(xmlFilePath)) {
return new ParseResult(false, "XML文件不存在: " + xmlFilePath);
}
// 解析XML文档
Document document = XmlUtil.readXML(new File(xmlFilePath));
Element rootElement = document.getDocumentElement();
// 创建TXT文件
File txtFile = new File(txtFilePath);
FileUtil.touch(txtFile);
// 解析XML并生成TXT内容
try (BufferedWriter writer = new BufferedWriter(new FileWriter(txtFile, StandardCharsets.UTF_8))) {
int elementCount = parseXmlElement(rootElement, writer, 0, parseRules, mapperRules);
// 生成统计信息
Map<String, Object> statistics = generateStatistics(document, elementCount);
log.info("XML文件解析成功共解析 {} 个元素", elementCount);
return new ParseResult(true, "XML文件解析成功", txtFilePath, elementCount, statistics);
} catch (IOException e) {
log.error("写入TXT文件失败: {}", e.getMessage(), e);
return new ParseResult(false, "写入TXT文件失败: " + e.getMessage());
}
} catch (Exception e) {
log.error("解析XML文件失败: {}", e.getMessage(), e);
return new ParseResult(false, "解析XML文件失败: " + e.getMessage());
}
}
/**
* 解析XML文件并转换为TXT格式使用默认规则
*
* @param xmlFilePath XML文件路径
* @param txtFilePath TXT文件输出路径
* @return 解析结果信息
*/
@Override
public ParseResult parseXmlToTxt(String xmlFilePath, String txtFilePath) {
// 使用默认解析规则和映射规则
List<ParseRuleDTO> defaultParseRules = getDefaultParseRules();
List<MapperRuleDTO> defaultMapperRules = getDefaultMapperRules();
return parseXmlToTxt(xmlFilePath, txtFilePath, defaultParseRules, defaultMapperRules);
}
/**
* 验证XML文件格式
*
* @param xmlFilePath XML文件路径
* @return 验证结果
*/
@Override
public ValidationResult validateXmlFile(String xmlFilePath) {
try {
if (!FileUtil.exist(xmlFilePath)) {
return new ValidationResult(false, "XML文件不存在");
}
// 尝试解析XML文件
Document document = XmlUtil.readXML(new File(xmlFilePath));
// 检查根元素
Element rootElement = document.getDocumentElement();
if (rootElement == null) {
return new ValidationResult(false, "XML文件缺少根元素");
}
// 检查编码
String xmlContent = FileUtil.readString(xmlFilePath, StandardCharsets.UTF_8);
if (!xmlContent.contains("encoding=\"UTF-8\"") && !xmlContent.contains("encoding='UTF-8'")) {
return new ValidationResult(false, "XML文件编码不是UTF-8");
}
return new ValidationResult(true, "XML文件格式验证通过");
} catch (Exception e) {
return new ValidationResult(false, "XML文件格式错误: " + e.getMessage());
}
}
/**
* 获取XML文件结构信息
*
* @param xmlFilePath XML文件路径
* @return 结构信息
*/
@Override
public XmlStructureInfo getXmlStructure(String xmlFilePath) {
try {
if (!FileUtil.exist(xmlFilePath)) {
return null;
}
Document document = XmlUtil.readXML(new File(xmlFilePath));
Element rootElement = document.getDocumentElement();
// 收集元素信息
List<String> elementNames = new ArrayList<>();
Map<String, Integer> elementCounts = new HashMap<>();
List<String> attributeNames = new ArrayList<>();
collectElementInfo(rootElement, elementNames, elementCounts, attributeNames);
int totalElements = elementNames.size();
int totalAttributes = attributeNames.size();
return new XmlStructureInfo(
rootElement.getTagName(),
totalElements,
totalAttributes,
elementNames,
elementCounts,
attributeNames
);
} catch (Exception e) {
log.error("获取XML结构信息失败: {}", e.getMessage(), e);
return null;
}
}
/**
* 递归解析XML元素
*
* @param element XML元素
* @param writer 写入器
* @param indentLevel 缩进级别
* @param parseRules 解析规则
* @param mapperRules 映射规则
* @return 解析的元素数量
*/
private int parseXmlElement(Element element, BufferedWriter writer, int indentLevel,
List<ParseRuleDTO> parseRules, List<MapperRuleDTO> mapperRules) throws IOException {
int elementCount = 0;
// 检查标签属性
String labelAttr = element.getAttribute(GlobalConstants.XMLTagType.XML_ATTR_LABEL);
String isNullAttr = element.getAttribute(GlobalConstants.XMLTagType.XML_ATTR_IS_NULL);
String nodeAttr = element.getAttribute(GlobalConstants.XMLTagType.XML_ATTR_NODE);
// 如果isNull="true"则跳过该元素
if ("true".equalsIgnoreCase(isNullAttr)) {
log.debug("跳过isNull=true的元素: {}", element.getTagName());
return elementCount;
}
// 如果node属性存在且不为空则跳过该元素
if (StrUtil.isNotBlank(nodeAttr)) {
log.debug("跳过node属性不为空的元素: {}", element.getTagName());
return elementCount;
}
// 生成缩进
String indent = " ".repeat(indentLevel);
// 处理当前元素
String elementName = element.getTagName();
String txtKey = getTxtKey(elementName, parseRules);
// 写入元素开始标记
if (indentLevel == 0) {
writer.write(txtKey);
} else {
writer.write(indent + txtKey);
}
// 如果有label属性添加注释
if (StrUtil.isNotBlank(labelAttr)) {
writer.write(" # " + labelAttr);
}
writer.newLine();
elementCount++;
// 处理子元素
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node childNode = childNodes.item(i);
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
Element childElement = (Element) childNode;
elementCount += parseXmlElement(childElement, writer, indentLevel + 1, parseRules, mapperRules);
} else if (childNode.getNodeType() == Node.TEXT_NODE) {
// 处理文本内容
String textContent = childNode.getTextContent().trim();
if (StrUtil.isNotBlank(textContent)) {
writer.write(indent + " " + textContent);
writer.newLine();
elementCount++;
}
}
}
// 写入元素结束标记
if (indentLevel > 0) {
writer.write(indent + "end_" + txtKey);
writer.newLine();
}
return elementCount;
}
/**
* 获取TXT文件中的键名
*
* @param xmlTag XML标签名
* @param parseRules 解析规则
* @return TXT键名
*/
private String getTxtKey(String xmlTag, List<ParseRuleDTO> parseRules) {
// 首先查找匹配的解析规则
if (parseRules != null) {
for (ParseRuleDTO rule : parseRules) {
if (xmlTag.equals(rule.getXmlTag())) {
return rule.getTxtKey();
}
}
}
// 如果没有匹配的规则使用默认转换
// 将中文标签转换为英文使用下划线分隔
return xmlTag.chars()
.mapToObj(c -> Character.isLetterOrDigit(c) ? String.valueOf((char) c) : "_")
.collect(Collectors.joining())
.replaceAll("_+", "_")
.toLowerCase();
}
/**
* 收集元素信息
*
* @param element XML元素
* @param elementNames 元素名称列表
* @param elementCounts 元素计数映射
* @param attributeNames 属性名称列表
*/
private void collectElementInfo(Element element, List<String> elementNames,
Map<String, Integer> elementCounts, List<String> attributeNames) {
String tagName = element.getTagName();
// 添加元素名称
if (!elementNames.contains(tagName)) {
elementNames.add(tagName);
}
// 更新元素计数
elementCounts.put(tagName, elementCounts.getOrDefault(tagName, 0) + 1);
// 收集属性名称
if (element.hasAttributes()) {
var attributes = element.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
String attrName = attributes.item(i).getNodeName();
if (!attributeNames.contains(attrName)) {
attributeNames.add(attrName);
}
}
}
// 递归处理子元素
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node childNode = childNodes.item(i);
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
collectElementInfo((Element) childNode, elementNames, elementCounts, attributeNames);
}
}
}
/**
* 生成统计信息
*
* @param document XML文档
* @param elementCount 元素数量
* @return 统计信息映射
*/
private Map<String, Object> generateStatistics(Document document, int elementCount) {
Map<String, Object> statistics = new HashMap<>();
statistics.put("totalElements", elementCount);
statistics.put("rootElement", document.getDocumentElement().getTagName());
statistics.put("parseTime", new Date());
return statistics;
}
/**
* 获取默认解析规则
*
* @return 默认解析规则列表
*/
private List<ParseRuleDTO> getDefaultParseRules() {
List<ParseRuleDTO> rules = new ArrayList<>();
// 添加默认解析规则
rules.add(createParseRule("任务", "task", "root"));
rules.add(createParseRule("任务信息", "task_info", "node"));
rules.add(createParseRule("任务行动信息", "action_info", "leaf"));
rules.add(createParseRule("指令有效期", "validity_period", "leaf"));
rules.add(createParseRule("指令确认信息", "confirmation_info", "leaf"));
rules.add(createParseRule("覆盖的指令文档", "covered_document", "leaf"));
rules.add(createParseRule("平台", "platform", "node"));
rules.add(createParseRule("平台名称", "platform_name", "leaf"));
rules.add(createParseRule("机型", "machine_type", "leaf"));
rules.add(createParseRule("架数", "num_of_cpus", "leaf"));
rules.add(createParseRule("平台识别码", "platform_id", "leaf"));
rules.add(createParseRule("国家", "country", "leaf"));
rules.add(createParseRule("行动", "action", "node"));
rules.add(createParseRule("航线名称", "route_name", "leaf"));
return rules;
}
/**
* 获取默认映射规则
*
* @return 默认映射规则列表
*/
private List<MapperRuleDTO> getDefaultMapperRules() {
List<MapperRuleDTO> rules = new ArrayList<>();
// 添加默认映射规则
rules.add(createMapperRule("task", "task", "direct"));
rules.add(createMapperRule("task_info", "task_info", "direct"));
rules.add(createMapperRule("action_info", "action_info", "direct"));
rules.add(createMapperRule("validity_period", "validity_period", "direct"));
rules.add(createMapperRule("confirmation_info", "confirmation_info", "direct"));
rules.add(createMapperRule("covered_document", "covered_document", "direct"));
rules.add(createMapperRule("platform", "platform", "direct"));
rules.add(createMapperRule("platform_name", "platform_name", "direct"));
rules.add(createMapperRule("machine_type", "machine_type", "direct"));
rules.add(createMapperRule("num_of_cpus", "num_of_cpus", "direct"));
rules.add(createMapperRule("platform_id", "platform_id", "direct"));
rules.add(createMapperRule("country", "country", "direct"));
rules.add(createMapperRule("action", "action", "direct"));
rules.add(createMapperRule("route_name", "route_name", "direct"));
return rules;
}
/**
* 创建解析规则DTO
*
* @param xmlTag XML标签
* @param txtKey TXT键名
* @param tagType 标签类型
* @return 解析规则DTO
*/
private ParseRuleDTO createParseRule(String xmlTag, String txtKey, String tagType) {
ParseRuleDTO rule = new ParseRuleDTO();
rule.setXmlTag(xmlTag);
rule.setTxtKey(txtKey);
rule.setTagType(tagType);
return rule;
}
/**
* 创建映射规则DTO
*
* @param parseRuleId 解析规则ID
* @param txtKey TXT键名
* @param mappingType 映射类型
* @return 映射规则DTO
*/
private MapperRuleDTO createMapperRule(String parseRuleId, String txtKey, String mappingType) {
MapperRuleDTO rule = new MapperRuleDTO();
rule.setParseRuleId(parseRuleId);
rule.setTxtKey(txtKey);
rule.setMappingType(mappingType);
return rule;
}
}

View File

@ -0,0 +1,358 @@
package com.example.demo.parser.util;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import com.example.demo.common.constant.GlobalConstants;
import com.example.demo.parser.service.XmlParserService;
import com.example.demo.parser.service.impl.XmlParserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
/**
* XML解析工具类
* 提供XML文件解析和转换的静态工具方法
*
* @author 岳佳君 (2025年09月28日 10:00:00)
* @version 1.0.0
*/
@Slf4j
public class XmlParserUtil {
/**
* 解析XML文件并转换为TXT格式
*
* @param xmlFilePath XML文件路径
* @param txtFilePath TXT文件输出路径
* @throws Exception 解析异常
*/
public static void parseXmlToTxt(String xmlFilePath, String txtFilePath) throws Exception {
log.info("开始解析XML文件: {} -> {}", xmlFilePath, txtFilePath);
// 验证文件存在性
if (!FileUtil.exist(xmlFilePath)) {
throw new IllegalArgumentException("XML文件不存在: " + xmlFilePath);
}
// 解析XML文档
Document document = XmlUtil.readXML(new File(xmlFilePath));
Element rootElement = document.getDocumentElement();
// 创建TXT文件
File txtFile = new File(txtFilePath);
FileUtil.touch(txtFile);
// 解析XML并生成TXT内容
try (BufferedWriter writer = new BufferedWriter(new FileWriter(txtFile, StandardCharsets.UTF_8))) {
parseXmlElement(rootElement, writer, 0);
log.info("XML文件解析成功: {}", txtFilePath);
} catch (IOException e) {
log.error("写入TXT文件失败: {}", e.getMessage(), e);
throw new IOException("写入TXT文件失败: " + e.getMessage(), e);
}
}
/**
* 递归解析XML元素
*
* @param element XML元素
* @param writer 写入器
* @param indentLevel 缩进级别
* @throws IOException IO异常
*/
private static void parseXmlElement(Element element, BufferedWriter writer, int indentLevel) throws IOException {
// 检查标签属性
String labelAttr = element.getAttribute(GlobalConstants.XMLTagType.XML_ATTR_LABEL);
String isNullAttr = element.getAttribute(GlobalConstants.XMLTagType.XML_ATTR_IS_NULL);
String nodeAttr = element.getAttribute(GlobalConstants.XMLTagType.XML_ATTR_NODE);
// 如果isNull="true"则跳过该元素
if ("true".equalsIgnoreCase(isNullAttr)) {
log.debug("跳过isNull=true的元素: {}", element.getTagName());
return;
}
// 如果node属性存在且不为空则跳过该元素
if (StrUtil.isNotBlank(nodeAttr)) {
log.debug("跳过node属性不为空的元素: {}", element.getTagName());
return;
}
// 生成缩进
String indent = " ".repeat(indentLevel);
// 处理当前元素
String elementName = element.getTagName();
String txtKey = convertToTxtKey(elementName);
// 写入元素开始标记
if (indentLevel == 0) {
writer.write(txtKey);
} else {
writer.write(indent + txtKey);
}
// 如果有label属性添加注释
if (StrUtil.isNotBlank(labelAttr)) {
writer.write(" # " + labelAttr);
}
writer.newLine();
// 处理子元素
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node childNode = childNodes.item(i);
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
Element childElement = (Element) childNode;
parseXmlElement(childElement, writer, indentLevel + 1);
} else if (childNode.getNodeType() == Node.TEXT_NODE) {
// 处理文本内容
String textContent = childNode.getTextContent().trim();
if (StrUtil.isNotBlank(textContent)) {
writer.write(indent + " " + textContent);
writer.newLine();
}
}
}
// 写入元素结束标记
if (indentLevel > 0) {
writer.write(indent + "end_" + txtKey);
writer.newLine();
}
}
/**
* 将XML标签转换为TXT键名
*
* @param xmlTag XML标签名
* @return TXT键名
*/
private static String convertToTxtKey(String xmlTag) {
// 定义默认的标签映射规则
switch (xmlTag) {
case "任务":
return "task";
case "任务信息":
return "task_info";
case "任务行动信息":
return "action_info";
case "指令有效期":
return "validity_period";
case "指令确认信息":
return "confirmation_info";
case "覆盖的指令文档":
return "covered_document";
case "平台":
return "platform";
case "平台名称":
return "platform_name";
case "机型":
return "machine_type";
case "架数":
return "num_of_cpus";
case "平台识别码":
return "platform_id";
case "国家":
return "country";
case "行动":
return "action";
case "航线名称":
return "route_name";
default:
// 对于未知标签使用默认转换规则
return xmlTag.toLowerCase().replaceAll("[^a-zA-Z0-9]", "_");
}
}
/**
* 验证XML文件格式
*
* @param xmlFilePath XML文件路径
* @return 验证结果
*/
public static boolean validateXmlFile(String xmlFilePath) {
try {
if (!FileUtil.exist(xmlFilePath)) {
log.error("XML文件不存在: {}", xmlFilePath);
return false;
}
// 尝试解析XML文件
Document document = XmlUtil.readXML(new File(xmlFilePath));
// 检查根元素
Element rootElement = document.getDocumentElement();
if (rootElement == null) {
log.error("XML文件缺少根元素: {}", xmlFilePath);
return false;
}
// 检查编码
String xmlContent = FileUtil.readString(xmlFilePath, StandardCharsets.UTF_8);
if (!xmlContent.contains("encoding=\"UTF-8\"") && !xmlContent.contains("encoding='UTF-8'")) {
log.warn("XML文件编码不是UTF-8: {}", xmlFilePath);
}
log.info("XML文件格式验证通过: {}", xmlFilePath);
return true;
} catch (Exception e) {
log.error("XML文件格式验证失败: {} - {}", xmlFilePath, e.getMessage(), e);
return false;
}
}
/**
* 获取XML文件中的标签列表
*
* @param xmlFilePath XML文件路径
* @return 标签列表
*/
public static List<String> getXmlTags(String xmlFilePath) {
List<String> tags = new ArrayList<>();
try {
if (!FileUtil.exist(xmlFilePath)) {
return tags;
}
Document document = XmlUtil.readXML(new File(xmlFilePath));
collectTags(document.getDocumentElement(), tags);
} catch (Exception e) {
log.error("获取XML标签列表失败: {}", e.getMessage(), e);
}
return tags;
}
/**
* 递归收集XML标签
*
* @param element XML元素
* @param tags 标签列表
*/
private static void collectTags(Element element, List<String> tags) {
if (element == null) {
return;
}
String tagName = element.getTagName();
if (!tags.contains(tagName)) {
tags.add(tagName);
}
// 递归处理子元素
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node childNode = childNodes.item(i);
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
collectTags((Element) childNode, tags);
}
}
}
/**
* 使用XML解析服务进行解析
*
* @param xmlFilePath XML文件路径
* @param txtFilePath TXT文件输出路径
* @return 解析结果
*/
public static XmlParserService.ParseResult parseWithService(String xmlFilePath, String txtFilePath) {
XmlParserService parserService = new XmlParserServiceImpl();
return parserService.parseXmlToTxt(xmlFilePath, txtFilePath);
}
/**
* 生成示例XML文件
*
* @param filePath 文件路径
* @return 是否生成成功
*/
public static boolean generateSampleXml(String filePath) {
try {
String sampleXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<任务>\n" +
" <任务信息>\n" +
" <任务行动信息>进行XXX任务</任务行动信息>\n" +
" <指令有效期>2023-08-01_01:00:00~2023-08-01_02:00:00</指令有效期>\n" +
" <指令确认信息>是</指令确认信息>\n" +
" <覆盖的指令文档>1.0</覆盖的指令文档>\n" +
" </任务信息>\n" +
" <平台>\n" +
" <平台名称>Windows</平台名称>\n" +
" <机型>x86_64</机型>\n" +
" <架数>1</架数>\n" +
" <平台识别码>Windows-10-10.0.19045</平台识别码>\n" +
" <国家>中国</国家>\n" +
" <行动 label=\"解析行动\">\n" +
" <航线名称>XXX航线</航线名称>\n" +
" </行动>\n" +
" <行动 isNull=\"true\">\n" +
" <!-- 解析行动B计划忽略该行动 -->\n" +
" </行动>\n" +
" <行动 node=\"xxxx\">\n" +
" <!-- 解析行动C计划忽略该行动 -->\n" +
" </行动>\n" +
" </平台>\n" +
"</任务>";
FileUtil.writeString(sampleXml, filePath, StandardCharsets.UTF_8);
log.info("示例XML文件生成成功: {}", filePath);
return true;
} catch (Exception e) {
log.error("生成示例XML文件失败: {}", e.getMessage(), e);
return false;
}
}
/**
* 生成示例TXT文件
*
* @param filePath 文件路径
* @return 是否生成成功
*/
public static boolean generateSampleTxt(String filePath) {
try {
String sampleTxt = "task 进行XXX任务 # 任务信息\n" +
" start_time 2023-08-01_01:00:00\n" +
" end_time 2023-08-01_02:00:00\n" +
"end_task\n" +
"\n" +
"platform # 平台信息\n" +
" platform_name Windows\n" +
" machine_type x86_64\n" +
" num_of_cpus 1\n" +
" platform_id Windows-10-10.0.19045\n" +
" country 中国\n" +
" action\n" +
" action_name 解析行动\n" +
" route_name XXX航线\n" +
" end_action\n" +
"end_platform";
FileUtil.writeString(sampleTxt, filePath, StandardCharsets.UTF_8);
log.info("示例TXT文件生成成功: {}", filePath);
return true;
} catch (Exception e) {
log.error("生成示例TXT文件失败: {}", e.getMessage(), e);
return false;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 KiB

View File

@ -0,0 +1,116 @@
-- 配置域数据库表结构设计
-- 将domain包中的配置类转换为数据库表结构
-- 配置文档表
CREATE TABLE IF NOT EXISTS config_document (
id TEXT PRIMARY KEY, -- 主键ID
name TEXT NOT NULL, -- 配置文档名称
global_comment TEXT, -- 全局备注信息
initial_indent TEXT DEFAULT '', -- 初始缩进配置
indent_spaces INTEGER DEFAULT 4, -- 缩进空格数
description TEXT, -- 描述信息
sort_order INTEGER DEFAULT 0, -- 排序顺序
created_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 更新时间
is_deleted INTEGER DEFAULT 0 -- 是否删除0:否, 1:是)
);
-- 条件类型映射表
CREATE TABLE IF NOT EXISTS condition_map (
id TEXT PRIMARY KEY, -- 主键ID
config_document_id TEXT NOT NULL, -- 配置文档ID
condition_key TEXT NOT NULL, -- 条件键
condition_value TEXT NOT NULL, -- 条件值
description TEXT, -- 描述信息
sort_order INTEGER DEFAULT 0, -- 排序顺序
created_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 更新时间
is_deleted INTEGER DEFAULT 0, -- 是否删除0:否, 1:是)
FOREIGN KEY (config_document_id) REFERENCES config_document(id) ON DELETE CASCADE
);
-- 层级配置表
CREATE TABLE IF NOT EXISTS level_config (
id TEXT PRIMARY KEY, -- 主键ID
config_document_id TEXT NOT NULL, -- 配置文档ID
level_name TEXT NOT NULL, -- 层级名称
level_loop_index TEXT, -- 层级值循环索引号
enable_level INTEGER DEFAULT 1, -- 是否启用层级0:否, 1:是)
level_values TEXT, -- 层级值列表JSON格式
comment TEXT, -- 层级注释说明
condition_type TEXT, -- 条件类型
enable_loop INTEGER DEFAULT 0, -- 是否启用循环0:否, 1:是)
loop_count TEXT, -- 循环次数
enum_mapping TEXT, -- 枚举映射配置JSON格式
util_function TEXT, -- 工具函数调用配置JSON格式
parent_id TEXT, -- 父级ID支持无限层级嵌套
sort_order INTEGER DEFAULT 0, -- 排序顺序
created_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 更新时间
is_deleted INTEGER DEFAULT 0, -- 是否删除0:否, 1:是)
FOREIGN KEY (config_document_id) REFERENCES config_document(id) ON DELETE CASCADE,
FOREIGN KEY (parent_id) REFERENCES level_config(id) ON DELETE CASCADE
);
-- 值配置表
CREATE TABLE IF NOT EXISTS value_config (
id TEXT PRIMARY KEY, -- 主键ID
level_config_id TEXT NOT NULL, -- 层级配置ID
value_name TEXT NOT NULL, -- 值配置名称
comment TEXT, -- 值配置注释
sort_order INTEGER DEFAULT 0, -- 排序顺序
created_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 更新时间
is_deleted INTEGER DEFAULT 0, -- 是否删除0:否, 1:是)
FOREIGN KEY (level_config_id) REFERENCES level_config(id) ON DELETE CASCADE
);
-- 配置值表
CREATE TABLE IF NOT EXISTS config_value (
id TEXT PRIMARY KEY, -- 主键ID
value_config_id TEXT NOT NULL, -- 值配置ID
value_data TEXT, -- 配置值JSON格式
value_unit TEXT, -- 值单位
combined INTEGER DEFAULT 0, -- 组合标志0:否, 1:是)
regex_pattern TEXT, -- 正则表达式模式
regex_replacement TEXT, -- 正则替换字符串
enum_mapping TEXT, -- 枚举映射配置JSON格式
util_function TEXT, -- 工具函数调用配置JSON格式
sort_order INTEGER DEFAULT 0, -- 排序顺序
created_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 更新时间
is_deleted INTEGER DEFAULT 0, -- 是否删除0:否, 1:是)
FOREIGN KEY (value_config_id) REFERENCES value_config(id) ON DELETE CASCADE
);
-- 创建索引
CREATE INDEX IF NOT EXISTS idx_config_document_name ON config_document(name);
CREATE INDEX IF NOT EXISTS idx_config_document_is_deleted ON config_document(is_deleted);
CREATE INDEX IF NOT EXISTS idx_condition_map_config_document_id ON condition_map(config_document_id);
CREATE INDEX IF NOT EXISTS idx_condition_map_condition_key ON condition_map(condition_key);
CREATE INDEX IF NOT EXISTS idx_condition_map_is_deleted ON condition_map(is_deleted);
CREATE INDEX IF NOT EXISTS idx_level_config_config_document_id ON level_config(config_document_id);
CREATE INDEX IF NOT EXISTS idx_level_config_level_name ON level_config(level_name);
CREATE INDEX IF NOT EXISTS idx_level_config_parent_id ON level_config(parent_id);
CREATE INDEX IF NOT EXISTS idx_level_config_is_deleted ON level_config(is_deleted);
CREATE INDEX IF NOT EXISTS idx_value_config_level_config_id ON value_config(level_config_id);
CREATE INDEX IF NOT EXISTS idx_value_config_value_name ON value_config(value_name);
CREATE INDEX IF NOT EXISTS idx_value_config_is_deleted ON value_config(is_deleted);
CREATE INDEX IF NOT EXISTS idx_config_value_value_config_id ON config_value(value_config_id);
CREATE INDEX IF NOT EXISTS idx_config_value_is_deleted ON config_value(is_deleted);
-- 插入默认配置文档数据
INSERT OR IGNORE INTO config_document (id, name, global_comment, description)
VALUES ('default-config-doc', '默认配置文档', '系统默认配置文档', '用于存储系统默认的配置结构');
-- 插入默认条件类型映射数据
INSERT OR IGNORE INTO condition_map (id, config_document_id, condition_key, condition_value, description)
VALUES
('condition-required', 'default-config-doc', 'required', '必须配置', '必须配置项'),
('condition-optional', 'default-config-doc', 'optional', '可选配置', '可选配置项'),
('condition-advanced', 'default-config-doc', 'advanced', '高级选项', '高级选项(需要权限)'),
('condition-deprecated', 'default-config-doc', 'deprecated', '已弃用', '已弃用(不推荐使用)');

View File

@ -32,3 +32,33 @@ INSERT OR IGNORE INTO mapper_rule (id, parse_rule_id, txt_key, mapping_type, map
('12', '12', 'country', 'direct', NULL, NULL, '国家映射', 12),
('13', '13', 'action', 'direct', NULL, NULL, '行动节点映射', 13),
('14', '14', 'route_name', 'direct', NULL, NULL, '航线名称映射', 14);
-- 插入默认的配置文档数据
INSERT OR IGNORE INTO config_document (id, document_name, document_type, description, sort_order, name, name_space, sort_name) VALUES
('config_doc_001', 'XML解析配置文档', 'xml_parser', 'XML到TXT转换的解析配置文档', 1, 'XML解析配置', 'parser', 'xml_parser_config');
-- 插入默认的条件类型映射数据
INSERT OR IGNORE INTO condition_map (id, config_document_id, condition_key, condition_value, description, sort_order, name, name_space, sort_name) VALUES
('cond_001', 'config_doc_001', 'platform_type', 'Windows', 'Windows平台条件', 1, 'Windows条件', 'platform', 'windows_condition'),
('cond_002', 'config_doc_001', 'platform_type', 'Linux', 'Linux平台条件', 2, 'Linux条件', 'platform', 'linux_condition'),
('cond_003', 'config_doc_001', 'task_type', '常规任务', '常规任务条件', 3, '常规任务条件', 'task', 'normal_task_condition');
-- 插入默认的层级配置数据
INSERT OR IGNORE INTO level_config (id, config_document_id, level_name, level_type, description, sort_order, name, name_space, sort_name) VALUES
('level_001', 'config_doc_001', '任务层级', 'task_level', '任务信息层级配置', 1, '任务层级', 'task', 'task_level'),
('level_002', 'config_doc_001', '平台层级', 'platform_level', '平台信息层级配置', 2, '平台层级', 'platform', 'platform_level'),
('level_003', 'config_doc_001', '行动层级', 'action_level', '行动信息层级配置', 3, '行动层级', 'action', 'action_level');
-- 插入默认的值配置数据
INSERT OR IGNORE INTO value_config (id, level_config_id, value_name, comment, sort_order, name, name_space, sort_name) VALUES
('value_001', 'level_001', '任务名称', '任务名称配置', 1, '任务名称配置', 'task', 'task_name_config'),
('value_002', 'level_001', '任务时间', '任务时间范围配置', 2, '任务时间配置', 'task', 'task_time_config'),
('value_003', 'level_002', '平台信息', '平台基本信息配置', 1, '平台信息配置', 'platform', 'platform_info_config'),
('value_004', 'level_003', '行动信息', '行动详细信息配置', 1, '行动信息配置', 'action', 'action_info_config');
-- 插入默认的配置值数据
INSERT OR IGNORE INTO config_value (id, value_config_id, value_data, value_unit, combined, regex_pattern, regex_replacement, sort_order, enable_value, condition_type, parent_id, name, name_space, sort_name) VALUES
('config_val_001', 'value_001', '{"default": "默认任务"}', NULL, 0, NULL, NULL, 1, 1, NULL, NULL, '默认任务值', 'task', 'default_task_value'),
('config_val_002', 'value_002', '{"format": "yyyy-MM-dd_HH:mm:ss"}', '时间', 0, '(\\d{4}-\\d{2}-\\d{2}_\\d{2}:\\d{2}:\\d{2})~(\\d{4}-\\d{2}-\\d{2}_\\d{2}:\\d{2}:\\d{2})', '$1,$2', 1, 1, 'time_range', NULL, '时间格式配置', 'time', 'time_format_config'),
('config_val_003', 'value_003', '{"platforms": ["Windows", "Linux", "MacOS"]}', NULL, 0, NULL, NULL, 1, 1, NULL, NULL, '平台列表', 'platform', 'platform_list'),
('config_val_004', 'value_004', '{"action_types": ["解析行动", "执行行动", "监控行动"]}', NULL, 0, NULL, NULL, 1, 1, NULL, NULL, '行动类型', 'action', 'action_types');

View File

@ -8,10 +8,13 @@ CREATE TABLE IF NOT EXISTS parse_rule (
tag_type TEXT NOT NULL, -- 标签类型element/element_with_attributes/text
txt_key TEXT NOT NULL, -- TXT文件中的键名
parent_tag TEXT, -- 父级标签
is_null TEXT, -- 是否允许为空0:不允许, 1:允许)
node_path TEXT, -- 节点路径
is_required INTEGER DEFAULT 0, -- 是否必填0:否, 1:是)
default_value TEXT, -- 默认值
description TEXT, -- 描述信息
sort_order INTEGER DEFAULT 0, -- 排序顺序
revision INTEGER DEFAULT 0, -- 乐观锁版本号
created_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 更新时间
is_deleted INTEGER DEFAULT 0 -- 是否删除0:否, 1:是)
@ -27,9 +30,16 @@ CREATE TABLE IF NOT EXISTS mapper_rule (
function_name TEXT, -- 函数名称
description TEXT, -- 描述信息
sort_order INTEGER DEFAULT 0, -- 排序顺序
name TEXT, -- 名称
name_space TEXT, -- 命名空间
sort_name TEXT, -- 排序字段
is_deleted TEXT DEFAULT '0', -- 是否删除0:未删除, 1:已删除)
revision INTEGER DEFAULT 0, -- 乐观锁版本号
created_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
created_id TEXT, -- 创建人ID
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 更新时间
is_deleted INTEGER DEFAULT 0, -- 是否删除0:否, 1:是)
updated_id TEXT, -- 更新人ID
tenant_id TEXT, -- 租户ID
FOREIGN KEY (parse_rule_id) REFERENCES parse_rule(id) ON DELETE CASCADE
);
@ -39,11 +49,128 @@ CREATE TABLE IF NOT EXISTS file_record (
file_name TEXT NOT NULL, -- 文件名称
file_path TEXT NOT NULL, -- 文件路径
file_size INTEGER, -- 文件大小(字节)
file_type TEXT, -- 文件类型xml, txt
status TEXT NOT NULL, -- 状态UPLOADED/PARSING/PARSED/PARSE_FAILED
message TEXT, -- 处理消息
upload_time DATETIME, -- 上传时间
process_time DATETIME, -- 处理时间
name TEXT, -- 名称
name_space TEXT, -- 命名空间
sort_name TEXT, -- 排序字段
is_deleted TEXT DEFAULT '0', -- 是否删除0:未删除, 1:已删除)
revision INTEGER DEFAULT 0, -- 乐观锁版本号
created_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
created_id TEXT, -- 创建人ID
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 更新时间
is_deleted INTEGER DEFAULT 0 -- 是否删除0:否, 1:是)
updated_id TEXT, -- 更新人ID
tenant_id TEXT, -- 租户ID
);
-- 配置文档表
CREATE TABLE IF NOT EXISTS config_document (
id TEXT PRIMARY KEY, -- 主键ID
document_name TEXT NOT NULL, -- 文档名称
document_type TEXT NOT NULL, -- 文档类型
description TEXT, -- 描述信息
sort_order INTEGER DEFAULT 0, -- 排序顺序
name TEXT, -- 名称
name_space TEXT, -- 命名空间
sort_name TEXT, -- 排序字段
is_deleted TEXT DEFAULT '0', -- 是否删除0:未删除, 1:已删除)
revision INTEGER DEFAULT 0, -- 乐观锁版本号
created_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
created_id TEXT, -- 创建人ID
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 更新时间
updated_id TEXT, -- 更新人ID
tenant_id TEXT -- 租户ID
);
-- 条件类型映射表
CREATE TABLE IF NOT EXISTS condition_map (
id TEXT PRIMARY KEY, -- 主键ID
config_document_id TEXT NOT NULL, -- 配置文档ID
condition_key TEXT NOT NULL, -- 条件键
condition_value TEXT NOT NULL, -- 条件值
description TEXT, -- 描述信息
sort_order INTEGER DEFAULT 0, -- 排序顺序
name TEXT, -- 名称
name_space TEXT, -- 命名空间
sort_name TEXT, -- 排序字段
is_deleted TEXT DEFAULT '0', -- 是否删除0:未删除, 1:已删除)
revision INTEGER DEFAULT 0, -- 乐观锁版本号
created_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
created_id TEXT, -- 创建人ID
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 更新时间
updated_id TEXT, -- 更新人ID
tenant_id TEXT, -- 租户ID
FOREIGN KEY (config_document_id) REFERENCES config_document(id) ON DELETE CASCADE
);
-- 层级配置表
CREATE TABLE IF NOT EXISTS level_config (
id TEXT PRIMARY KEY, -- 主键ID
config_document_id TEXT NOT NULL, -- 配置文档ID
level_name TEXT NOT NULL, -- 层级名称
level_type TEXT NOT NULL, -- 层级类型
description TEXT, -- 描述信息
sort_order INTEGER DEFAULT 0, -- 排序顺序
name TEXT, -- 名称
name_space TEXT, -- 命名空间
sort_name TEXT, -- 排序字段
is_deleted TEXT DEFAULT '0', -- 是否删除0:未删除, 1:已删除)
revision INTEGER DEFAULT 0, -- 乐观锁版本号
created_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
created_id TEXT, -- 创建人ID
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 更新时间
updated_id TEXT, -- 更新人ID
tenant_id TEXT, -- 租户ID
FOREIGN KEY (config_document_id) REFERENCES config_document(id) ON DELETE CASCADE
);
-- 值配置表
CREATE TABLE IF NOT EXISTS value_config (
id TEXT PRIMARY KEY, -- 主键ID
level_config_id TEXT NOT NULL, -- 层级配置ID
value_name TEXT NOT NULL, -- 值配置名称
comment TEXT, -- 值配置注释
sort_order INTEGER DEFAULT 0, -- 排序顺序
name TEXT, -- 名称
name_space TEXT, -- 命名空间
sort_name TEXT, -- 排序字段
is_deleted TEXT DEFAULT '0', -- 是否删除0:未删除, 1:已删除)
revision INTEGER DEFAULT 0, -- 乐观锁版本号
created_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
created_id TEXT, -- 创建人ID
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 更新时间
updated_id TEXT, -- 更新人ID
tenant_id TEXT, -- 租户ID
FOREIGN KEY (level_config_id) REFERENCES level_config(id) ON DELETE CASCADE
);
-- 配置值表
CREATE TABLE IF NOT EXISTS config_value (
id TEXT PRIMARY KEY, -- 主键ID
value_config_id TEXT NOT NULL, -- 值配置ID
value_data TEXT NOT NULL, -- 配置值JSON格式
value_unit TEXT, -- 值单位
combined INTEGER DEFAULT 0, -- 组合标志
regex_pattern TEXT, -- 正则表达式模式
regex_replacement TEXT, -- 正则替换字符串
sort_order INTEGER DEFAULT 0, -- 排序顺序
enable_value INTEGER DEFAULT 1, -- 是否启用值0:否, 1:是)
condition_type TEXT, -- 条件类型
parent_id TEXT, -- 父级ID
name TEXT, -- 名称
name_space TEXT, -- 命名空间
sort_name TEXT, -- 排序字段
is_deleted TEXT DEFAULT '0', -- 是否删除0:未删除, 1:已删除)
revision INTEGER DEFAULT 0, -- 乐观锁版本号
created_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
created_id TEXT, -- 创建人ID
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP, -- 更新时间
updated_id TEXT, -- 更新人ID
tenant_id TEXT, -- 租户ID
FOREIGN KEY (value_config_id) REFERENCES value_config(id) ON DELETE CASCADE
);
-- 创建索引
@ -61,3 +188,25 @@ CREATE INDEX IF NOT EXISTS idx_mapper_rule_is_deleted ON mapper_rule(is_deleted)
CREATE INDEX IF NOT EXISTS idx_file_record_file_name ON file_record(file_name);
CREATE INDEX IF NOT EXISTS idx_file_record_status ON file_record(status);
CREATE INDEX IF NOT EXISTS idx_file_record_is_deleted ON file_record(is_deleted);
CREATE INDEX IF NOT EXISTS idx_config_document_name ON config_document(document_name);
CREATE INDEX IF NOT EXISTS idx_config_document_type ON config_document(document_type);
CREATE INDEX IF NOT EXISTS idx_config_document_is_deleted ON config_document(is_deleted);
CREATE INDEX IF NOT EXISTS idx_condition_map_document_id ON condition_map(config_document_id);
CREATE INDEX IF NOT EXISTS idx_condition_map_key ON condition_map(condition_key);
CREATE INDEX IF NOT EXISTS idx_condition_map_is_deleted ON condition_map(is_deleted);
CREATE INDEX IF NOT EXISTS idx_level_config_document_id ON level_config(config_document_id);
CREATE INDEX IF NOT EXISTS idx_level_config_name ON level_config(level_name);
CREATE INDEX IF NOT EXISTS idx_level_config_is_deleted ON level_config(is_deleted);
CREATE INDEX IF NOT EXISTS idx_value_config_level_id ON value_config(level_config_id);
CREATE INDEX IF NOT EXISTS idx_value_config_name ON value_config(value_name);
CREATE INDEX IF NOT EXISTS idx_value_config_is_deleted ON value_config(is_deleted);
CREATE INDEX IF NOT EXISTS idx_config_value_value_id ON config_value(value_config_id);
CREATE INDEX IF NOT EXISTS idx_config_value_enable ON config_value(enable_value);
CREATE INDEX IF NOT EXISTS idx_config_value_condition ON config_value(condition_type);
CREATE INDEX IF NOT EXISTS idx_config_value_parent ON config_value(parent_id);
CREATE INDEX IF NOT EXISTS idx_config_value_is_deleted ON config_value(is_deleted);