模版编制的相关实现

This commit is contained in:
潘荣晟
2025-09-22 17:12:46 +08:00
parent 58e2827a21
commit c14837b5e2
22 changed files with 567 additions and 15 deletions

View File

@@ -52,6 +52,14 @@ public class TemplateInstanceDataController implements BusinessControllerMarker
return success(templateInstanceDataService.createTemplateInstanceData(createReqVO));
}
@PostMapping("/create-batch")
@Operation(summary = "批量创建实例字段值")
@PreAuthorize("@ss.hasPermission('base:template-instance-data:create')")
public CommonResult<List<TemplateInstanceDataRespVO>> createBatchTemplateInstanceData(@Valid @RequestBody List<TemplateInstanceDataSaveReqVO> createReqVOS) {
return success(templateInstanceDataService.createBatchTemplateInstanceData(createReqVOS));
}
@PutMapping("/update")
@Operation(summary = "更新实例字段值")
@PreAuthorize("@ss.hasPermission('base:template-instance-data:update')")

View File

@@ -51,6 +51,13 @@ public class TemplateInstanceItemController implements BusinessControllerMarker
return success(templateInstanceItemService.createTemplateInstanceItem(createReqVO));
}
@PostMapping("/create-batch")
@Operation(summary = "批量创建实例条款值")
@PreAuthorize("@ss.hasPermission('base:template-instance-item:create')")
public CommonResult<List<TemplateInstanceItemRespVO>> createBatchTemplateInstanceItem(@Valid @RequestBody List<TemplateInstanceItemSaveReqVO> createReqVOS) {
return success(templateInstanceItemService.createBatchTemplateInstanceItem(createReqVOS));
}
@PutMapping("/update")
@Operation(summary = "更新实例条款值")
@PreAuthorize("@ss.hasPermission('base:template-instance-item:update')")

View File

@@ -59,4 +59,10 @@ public class TmplTpFldController {
PageResult<TmplTpFldDO> pageResult = tmplTpFldService.tmplTpFldPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, TmplFldRespVO.class));
}
@GetMapping("/getByClass")
@Operation(summary = "获得类固定模板字段列表")
@PreAuthorize("@ss.hasPermission('bse:tmpl-tp-fld:list')")
public CommonResult<List<Map<String, Object>>> getTmplTpListByClass(String clazz) {
return success(tmplTpFldService.getTmplTpListByClass(clazz));
}
}

View File

@@ -39,7 +39,7 @@ public class TemplateInstanceSaveReqVO {
private String fileTp;
@Schema(description = "版本号;如v1.0", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "版本号;如v1.0不能为空")
//@NotEmpty(message = "版本号;如v1.0不能为空")
private String ver;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@@ -49,6 +49,6 @@ public class TemplateInstanceSaveReqVO {
@Schema(description = "使用部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotEmpty(message = "使用部门编号不能为空")
private List<Long> deptIds;
private List<String> deptIds;
}

View File

@@ -16,7 +16,7 @@ public class TmplTpFldSaveReqVO {
@Schema(description = "字段数据类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "string")
private String datTp;
@Schema(description = "字段描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "代码")
private JSONObject fldDoc;
private String fldDoc;
@Schema(description = "字段备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "代码")
private String rmk;
@Schema(description = "是否必填", requiredMode = Schema.RequiredMode.REQUIRED, example = "Y or N")

View File

@@ -27,7 +27,7 @@ public class DepartmentInstanceRelativityDO extends BusinessBaseDO {
/**
* 主键
*/
@TableId(type = IdType.INPUT)
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
* 部门主键

View File

@@ -27,7 +27,7 @@ public class TemplateInstanceItemDO extends BusinessBaseDO {
/**
* 主键
*/
@TableId(type = IdType.INPUT)
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
* 关联实例主键

View File

@@ -12,8 +12,8 @@ import java.time.LocalDateTime;
*
* @author 后台管理
*/
@TableName("BIZ_TMPL_TP_FLD")
@KeySequence("BIZ_TMPL_TP_FLD_SEQ")
@TableName("BSE_TMPL_TP_FLD")
@KeySequence("BSE_TMPL_TP_FLD_SEQ")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@@ -68,4 +68,11 @@ public class TmplTpFldDO extends BusinessBaseDO { // 继承业务基类,自动
*/
@TableField("IS_MUST")
private String isMust;
/**
* 是否必填(对应表中 IS_MUST 字段VARCHAR2(10) 类型,非空)
* 建议值Y、N需在业务层做枚举校验
*/
@TableField("ORGN_TP")
private String orgnTp;
}

View File

@@ -9,6 +9,7 @@ import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
import com.zt.plat.module.base.controller.admin.templtp.vo.TemplateInstanceDataPageReqVO;
import com.zt.plat.module.base.dal.dataobject.tmpltp.TemplateInstanceDataDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
@@ -27,5 +28,6 @@ public interface TemplateInstanceDataMapper extends BaseMapperX<TemplateInstance
.betweenIfPresent(TemplateInstanceDataDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(TemplateInstanceDataDO::getId));
}
int deleteByTemplateInstanceId(@Param("templateInstanceId") Long templateInstanceId);
}

View File

@@ -9,6 +9,7 @@ import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
import com.zt.plat.module.base.controller.admin.templtp.vo.TemplateInstanceItemPageReqVO;
import com.zt.plat.module.base.dal.dataobject.tmpltp.TemplateInstanceItemDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
@@ -28,4 +29,5 @@ public interface TemplateInstanceItemMapper extends BaseMapperX<TemplateInstance
.orderByDesc(TemplateInstanceItemDO::getId));
}
int deleteByTemplateInstanceId(@Param("templateInstanceId") Long templateInstanceId);
}

View File

@@ -0,0 +1,32 @@
package com.zt.plat.module.base.framework.util.config;
import com.zt.plat.module.base.util.ClassInfoScanner;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
@Configuration
@Slf4j
public class UtilConfig {
// 固定的包路径,直接写死在代码中
private static final String BASE_PACKAGES = "com.zt.plat.module.base.controller.admin";
/**
* 当Spring容器初始化该配置类后自动执行初始化操作
*/
@PostConstruct
public void initClassInfoScanner() {
try {
// 使用固定的包路径初始化类信息扫描工具
ClassInfoScanner.init(BASE_PACKAGES);
log.info("ClassInfoScanner初始化成功扫描包路径【{}】" , BASE_PACKAGES);
} catch (Exception e) {
log.error("ClassInfoScanner初始化失败{}", e.getMessage());
//throw new RuntimeException("类信息扫描工具初始化失败", e);
}
}
}

View File

@@ -80,4 +80,6 @@ public interface TemplateInstanceDataService {
*/
boolean clearTemplateInstanceData(String instanceId,List<Long> valIds);
List<TemplateInstanceDataRespVO> createBatchTemplateInstanceData(List<TemplateInstanceDataSaveReqVO> createReqVOS);
}

View File

@@ -103,7 +103,7 @@ public class TemplateInstanceDataServiceImpl implements TemplateInstanceDataServ
if (CollUtil.isEmpty(pageReqVOS)) {
throw exception(PARAMS_IS_NULL_OR_ERR);
}
return templateInstanceDataMapper.insertBatch(pageReqVOS);
return templateInstanceDataMapper.updateBatch(pageReqVOS);
}
@Override
@@ -119,5 +119,15 @@ public class TemplateInstanceDataServiceImpl implements TemplateInstanceDataServ
return true;
}
@Override
public List<TemplateInstanceDataRespVO> createBatchTemplateInstanceData(List<TemplateInstanceDataSaveReqVO> createReqVOS) {
if (CollUtil.isEmpty(createReqVOS)) {
throw exception(PARAMS_IS_NULL_OR_ERR);
}
List<TemplateInstanceDataDO> templateInstanceDataDOList = BeanUtils.toBean(createReqVOS, TemplateInstanceDataDO.class);
templateInstanceDataMapper.insertBatch(templateInstanceDataDOList);
return BeanUtils.toBean(templateInstanceDataDOList, TemplateInstanceDataRespVO.class);
}
}

View File

@@ -61,6 +61,7 @@ public interface TemplateInstanceItemService {
* @param pageReqVO 分页查询
* @return 实例条款值分页
*/
PageResult<TemplateInstanceItemDO> getTemplateInstanceItemPage(TemplateInstanceItemPageReqVO pageReqVO);
PageResult<TemplateInstanceItemDO> getTemplateInstanceItemPage(@Valid TemplateInstanceItemPageReqVO pageReqVO);
List<TemplateInstanceItemRespVO> createBatchTemplateInstanceItem(@Valid List<TemplateInstanceItemSaveReqVO> createReqVOS);
}

View File

@@ -13,6 +13,7 @@ import java.util.*;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.util.object.BeanUtils;
import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.module.tmpltp.enums.ErrorCodeConstants.PARAMS_IS_NULL_OR_ERR;
import static com.zt.plat.module.tmpltp.enums.ErrorCodeConstants.TEMPLATE_INSTANCE_ITEM_NOT_EXISTS;
/**
@@ -84,4 +85,14 @@ public class TemplateInstanceItemServiceImpl implements TemplateInstanceItemServ
return templateInstanceItemMapper.selectPage(pageReqVO);
}
@Override
public List<TemplateInstanceItemRespVO> createBatchTemplateInstanceItem(List<TemplateInstanceItemSaveReqVO> createReqVOS) {
if (CollUtil.isEmpty(createReqVOS)) {
throw exception(PARAMS_IS_NULL_OR_ERR);
}
List<TemplateInstanceItemDO> templateInstanceItemDOList = BeanUtils.toBean(createReqVOS, TemplateInstanceItemDO.class);
templateInstanceItemMapper.insertBatch(templateInstanceItemDOList);
return BeanUtils.toBean(templateInstanceItemDOList, TemplateInstanceItemRespVO.class);
}
}

View File

@@ -9,15 +9,21 @@ import com.zt.plat.module.base.controller.admin.templtp.vo.TemplateInstanceSaveR
import com.zt.plat.module.base.dal.dataobject.tmpltp.DepartmentInstanceRelativityDO;
import com.zt.plat.module.base.dal.dataobject.tmpltp.TemplateInstanceDO;
import com.zt.plat.module.base.dal.mysql.tmpltp.DepartmentInstanceRelativityMapper;
import com.zt.plat.module.base.dal.mysql.tmpltp.TemplateInstanceDataMapper;
import com.zt.plat.module.base.dal.mysql.tmpltp.TemplateInstanceItemMapper;
import com.zt.plat.module.base.dal.mysql.tmpltp.TemplateInstanceMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.module.tmpltp.enums.ErrorCodeConstants.STATUS_OPERATION_FAIL;
import static com.zt.plat.module.tmpltp.enums.ErrorCodeConstants.TEMPLATE_INSTANCE_NOT_EXISTS;
@@ -34,8 +40,14 @@ public class TemplateInstanceServiceImpl implements TemplateInstanceService {
private TemplateInstanceMapper templateInstanceMapper;
@Resource
private DepartmentInstanceRelativityMapper departmentInstanceRelativityMapper;
@Resource
private TemplateInstanceDataMapper templateInstanceDataMapper;
@Resource
private TemplateInstanceItemMapper templateInstanceItemMapper;
private static final Pattern VERSION_PATTERN = Pattern.compile("^(.*?)([0-9]+(?:\\.[0-9]+)*)(.*)$");
@Override
@Transactional
public TemplateInstanceRespVO createTemplateInstance(TemplateInstanceSaveReqVO createReqVO) {
// 插入
TemplateInstanceDO templateInstance = BeanUtils.toBean(createReqVO, TemplateInstanceDO.class);
@@ -46,7 +58,7 @@ public class TemplateInstanceServiceImpl implements TemplateInstanceService {
createReqVO.getDeptIds().forEach(deptId ->{
DepartmentInstanceRelativityDO departmentInstanceRelativityDO = new DepartmentInstanceRelativityDO();
departmentInstanceRelativityDO.setTemplateInstanceId(String.valueOf(templateInstance.getId()));
departmentInstanceRelativityDO.setCompanyId(deptId);
departmentInstanceRelativityDO.setCompanyDepartmentId(deptId);
departmentInstanceRelativityDOS.add(departmentInstanceRelativityDO);
});
departmentInstanceRelativityMapper.insertBatch(departmentInstanceRelativityDOS);
@@ -58,20 +70,33 @@ public class TemplateInstanceServiceImpl implements TemplateInstanceService {
public void updateTemplateInstance(TemplateInstanceSaveReqVO updateReqVO) {
// 校验存在
validateTemplateInstanceExists(updateReqVO.getId());
// TemplateInstanceDO templateInstanceDO = templateInstanceMapper.selectById(updateReqVO.getId());
// TemplateInstanceDO templateInstanceDO = templateInstanceMapper.selectById(updateReqVO.getId());
// //获取保存旧文件内容防止被更新
// String originalContent = templateInstanceDO.getOriginalContent();
// 更新
TemplateInstanceDO templateInstanceDO = templateInstanceMapper.selectById(updateReqVO.getId());
String sts = templateInstanceDO.getSts();
if (!sts.equals("DRF")) {
throw exception(STATUS_OPERATION_FAIL);
}
TemplateInstanceDO updateObj = BeanUtils.toBean(updateReqVO, TemplateInstanceDO.class);
updateObj.setOrigCntt(null); //重新赋值,防止原始文件被更改
updateObj.setVer(incrementVersion(templateInstanceDO.getVer()));
templateInstanceMapper.updateById(updateObj);
}
@Override
@Transactional
public void deleteTemplateInstance(Long id) {
// 校验存在
validateTemplateInstanceExists(id);
// 删除
//删除对应的字段和条款关系
//1、删除合同的与字段的关系
templateInstanceDataMapper.deleteByTemplateInstanceId(id);
//2、删除条款与和他的关系
templateInstanceDataMapper.deleteByTemplateInstanceId(id);
templateInstanceMapper.deleteById(id);
}
@@ -106,4 +131,62 @@ public class TemplateInstanceServiceImpl implements TemplateInstanceService {
return templateInstanceMapper.selectPage(pageReqVO);
}
private String incrementVersion(String currentVersion) {
// 处理空值或空字符串
if (currentVersion == null || currentVersion.trim().isEmpty()) {
return "v1.0";
}
String version = currentVersion.trim();
Matcher matcher = VERSION_PATTERN.matcher(version);
if (!matcher.matches()) {
// 没有找到数字部分,返回默认版本
return version + "1.0";
}
String prefix = matcher.group(1); // 前缀部分(如 "v", "version-" 等)
String numberPart = matcher.group(2); // 数字部分(如 "1.2.3"
String suffix = matcher.group(3); // 后缀部分
// 分割数字部分
String[] segments = numberPart.split("\\.");
// 从最后一段开始处理进位
boolean carry = true; // 初始需要加1
for (int i = segments.length - 1; i >= 0 && carry; i--) {
try {
int currentNumber = Integer.parseInt(segments[i]);
currentNumber++; // 加1
if (currentNumber >= 10) {
// 需要进位
segments[i] = "0";
carry = true; // 继续向前进位
} else {
// 不需要进位
segments[i] = String.valueOf(currentNumber);
carry = false; // 停止进位
}
} catch (NumberFormatException e) {
// 理论上不会发生,因为正则已经保证了是数字
segments[i] = "1";
carry = false;
}
}
// 如果最高位也需要进位,在前面添加一段
if (carry) {
String[] newSegments = new String[segments.length + 1];
newSegments[0] = "1";
System.arraycopy(segments, 0, newSegments, 1, segments.length);
segments = newSegments;
}
// 重新组合版本号
String newNumberPart = String.join(".", segments);
return prefix + newNumberPart + suffix;
}
}

View File

@@ -10,11 +10,13 @@ import com.baomidou.mybatisplus.extension.service.IService;
import jakarta.validation.Valid;
import java.util.List;
import java.util.Map;
public interface TmplTpFldService extends IService<TmplTpFldDO> {
TmplFldRespVO createTmplFld(@Valid TmplTpFldSaveReqVO tmplTpFldSaveReqVO);
void updateTmplFld(@Valid TmplTpFldSaveReqVO tmplTpFldSaveReqVO);
PageResult<TmplTpFldDO> tmplTpFldPage(@Valid TmplFldPageReqVO pageReqVO);
PageResult<TmplTpFldDO> tmplTpFldPage(TmplFldPageReqVO pageReqVO);
void deleteTmplTpByIds(List< Long> ids);
List<Map<String, Object>>getTmplTpListByClass(String clazz);
}

View File

@@ -13,14 +13,19 @@ import com.zt.plat.module.base.dal.mysql.tmpltp.TmplTpFldMapper;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zt.plat.module.base.util.ClassInfoScanner;
import io.swagger.v3.oas.annotations.media.Schema;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.module.tmpltp.enums.ErrorCodeConstants.TMPL_FLD_CODE_EXISTS;
import static com.zt.plat.module.tmpltp.enums.ErrorCodeConstants.TMPL_FLD_NOT_EXISTS;
import static com.zt.plat.module.tmpltp.enums.ErrorCodeConstants.*;
@Service
@@ -73,4 +78,9 @@ public class TmplTpFldServiceImpl extends ServiceImpl<TmplTpFldMapper, TmplTpFld
validateTmplFldExists(ids);
baseMapper.deleteByIds(ids);
}
@Override
public List<Map<String, Object>> getTmplTpListByClass(String clazz) {
return ClassInfoScanner.getClassFieldInfo(clazz);
}
}

View File

@@ -0,0 +1,357 @@
package com.zt.plat.module.base.util;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ClassUtils;
import org.springframework.util.ResourceUtils;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* 类信息扫描工具类用于通过简单类名获取类字段及Schema注解信息
* 增强版:支持通配符包路径扫描
*/
@Slf4j
public class ClassInfoScanner {
// 缓存简单类名到Class的映射提高性能
private static final Map<String, Class<?>> CLASS_CACHE = new HashMap<>();
// 已初始化标识
private static boolean initialized = false;
/**
* 初始化扫描指定包路径下的所有类
* @param basePackages 基础包路径,支持逗号分隔多个包,支持*和**通配符
*/
public static synchronized void init(String basePackages) {
if (initialized) {
return;
}
if (basePackages == null || basePackages.trim().isEmpty()) {
throw new IllegalArgumentException("基础包路径不能为空");
}
String[] packages = basePackages.split("[,;\\s]+");
for (String pkg : packages) {
String trimmedPkg = pkg.trim();
if (trimmedPkg.contains("**") || trimmedPkg.contains("*")) {
// 处理通配符包路径
scanPackageWithWildcard(trimmedPkg);
log.info("已扫描通配符包路径:{}", trimmedPkg);
} else {
// 处理普通包路径
scanPackage(trimmedPkg);
log.info("已扫描普通包路径:{}", trimmedPkg);
}
}
initialized = true;
}
/**
* 处理包含通配符的包路径扫描
*/
private static void scanPackageWithWildcard(String wildcardPackage) {
try {
// 提取基础包路径(通配符之前的部分)
String basePackage = extractBasePackage(wildcardPackage);
String pattern = wildcardPackage.substring(basePackage.length());
// 扫描基础包路径
String packageDirName = basePackage.replace('.', '/');
Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
String protocol = url.getProtocol();
if ("file".equals(protocol)) {
String filePath = URLDecoder.decode(url.getFile(), StandardCharsets.UTF_8);
findClassesWithPattern(basePackage, filePath, pattern);
} else if ("jar".equals(protocol)) {
JarFile jar = ((JarURLConnection) url.openConnection()).getJarFile();
Enumeration<JarEntry> entries = jar.entries();
processJarEntriesWithPattern(basePackage, entries, pattern);
}
}
} catch (IOException e) {
throw new RuntimeException("扫描通配符包时发生错误: " + wildcardPackage, e);
}
}
/**
* 提取基础包路径(通配符之前的部分)
*/
private static String extractBasePackage(String wildcardPackage) {
int wildcardIndex = wildcardPackage.indexOf('*');
if (wildcardIndex == -1) {
return wildcardPackage;
}
String beforeWildcard = wildcardPackage.substring(0, wildcardIndex);
int lastDotIndex = beforeWildcard.lastIndexOf('.');
if (lastDotIndex == -1) {
return "";
}
return beforeWildcard.substring(0, lastDotIndex);
}
/**
* 在文件系统中按模式查找类
*/
private static void findClassesWithPattern(String basePackage, String basePath, String pattern) {
File baseDir = new File(basePath);
if (!baseDir.exists() || !baseDir.isDirectory()) {
return;
}
findClassesRecursive(baseDir, basePackage, pattern);
}
/**
* 递归查找匹配模式的类
*/
private static void findClassesRecursive(File dir, String packageName, String pattern) {
File[] files = dir.listFiles();
if (files == null) {
return;
}
for (File file : files) {
if (file.isDirectory()) {
// 递归处理子目录
String subPackageName = packageName + "." + file.getName();
findClassesRecursive(file, subPackageName, pattern);
} else if (file.getName().endsWith(".class")) {
// 检查是否匹配模式
String className = file.getName().substring(0, file.getName().length() - 6);
String fullClassName = packageName + "." + className;
if (matchesPattern(fullClassName, pattern)) {
try {
Class<?> clazz = Class.forName(fullClassName);
CLASS_CACHE.put(clazz.getSimpleName(), clazz);
} catch (ClassNotFoundException e) {
// 忽略无法加载的类
}
}
}
}
}
/**
* 在JAR包中按模式查找类
*/
private static void processJarEntriesWithPattern(String basePackage, Enumeration<JarEntry> entries, String pattern) {
String basePackagePath = basePackage.replace('.', '/');
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String entryName = entry.getName();
if (entryName.charAt(0) == '/') {
entryName = entryName.substring(1);
}
if (entryName.startsWith(basePackagePath) && !entry.isDirectory() && entryName.endsWith(".class")) {
String className = entryName.substring(0, entryName.length() - 6).replace('/', '.');
if (matchesPattern(className, pattern)) {
try {
Class<?> clazz = Class.forName(className);
CLASS_CACHE.put(clazz.getSimpleName(), clazz);
} catch (ClassNotFoundException e) {
// 忽略无法加载的类
}
}
}
}
}
/**
* 检查类名是否匹配通配符模式
*/
private static boolean matchesPattern(String className, String pattern) {
if (pattern.isEmpty()) {
return true;
}
// 简单的通配符匹配实现
if (pattern.startsWith(".")) {
pattern = pattern.substring(1);
}
// 处理 **.vo 模式
if (pattern.equals("**.vo")) {
return className.endsWith(".vo") ||
(className.contains(".") && className.substring(className.lastIndexOf('.') + 1).toLowerCase().contains("vo"));
}
// 处理其他模式
String[] patternParts = pattern.split("\\*\\*");
if (patternParts.length == 2) {
String prefix = patternParts[0];
String suffix = patternParts[1];
return className.contains(prefix) && className.endsWith(suffix);
}
return className.contains(pattern.replace("*", ""));
}
/**
* 通过简单类名获取类的字段及Schema注解信息
* @param simpleClassName 简单类名
* @return 包含字段名和label的列表
*/
public static List<Map<String, Object>> getClassFieldInfo(String simpleClassName) {
if (!initialized) {
throw new IllegalStateException("工具类未初始化请先调用init方法");
}
if (simpleClassName == null || !simpleClassName.endsWith("VO")) {
throw new IllegalArgumentException("参数为空或格式错误");
}
Class<?> targetClass = CLASS_CACHE.get(simpleClassName);
if (targetClass == null) {
throw new RuntimeException("未找到类: " + simpleClassName);
}
List<Map<String, Object>> resultList = new ArrayList<>();
Field[] fields = targetClass.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Schema.class)) {
Schema schema = field.getAnnotation(Schema.class);
Map<String, Object> fieldMap = new HashMap<>();
fieldMap.put("fieldName", field.getName());
fieldMap.put("label", schema.description().isEmpty() ?null:schema.description().split(";")[0]);
fieldMap.put("required", schema.requiredMode() == Schema.RequiredMode.REQUIRED);
fieldMap.put("example", schema.example());
fieldMap.put("orgnType", "class");
resultList.add(fieldMap);
}
}
return resultList;
}
/**
* 扫描指定包下的所有类(原有方法保持不变)
*/
private static void scanPackage(String basePackage) {
try {
String packageDirName = basePackage.replace('.', '/');
Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
String protocol = url.getProtocol();
if ("file".equals(protocol)) {
String filePath = URLDecoder.decode(url.getFile(), StandardCharsets.UTF_8.name());
findAndAddClassesInPackageByFile(basePackage, filePath);
} else if ("jar".equals(protocol)) {
JarFile jar = ((JarURLConnection) url.openConnection()).getJarFile();
Enumeration<JarEntry> entries = jar.entries();
processJarEntries(basePackage, entries);
}
}
} catch (IOException e) {
throw new RuntimeException("扫描包时发生错误: " + basePackage, e);
}
}
/**
* 处理文件系统中的类文件
*/
private static void findAndAddClassesInPackageByFile(String packageName, String packagePath) {
File dir = new File(packagePath);
if (!dir.exists() || !dir.isDirectory()) {
return;
}
File[] dirFiles = dir.listFiles(file ->
(file.isDirectory()) || (file.getName().endsWith(".class"))
);
if (dirFiles == null) {
return;
}
for (File file : dirFiles) {
if (file.isDirectory()) {
findAndAddClassesInPackageByFile(packageName + "." + file.getName(),
file.getAbsolutePath());
} else {
String className = file.getName().substring(0, file.getName().length() - 6);
try {
Class<?> clazz = Class.forName(packageName + '.' + className);
CLASS_CACHE.put(clazz.getSimpleName(), clazz);
} catch (ClassNotFoundException e) {
// 忽略无法加载的类
}
}
}
}
/**
* 处理JAR包中的类
*/
private static void processJarEntries(String basePackage, Enumeration<JarEntry> entries) {
String packageDirName = basePackage.replace('.', '/');
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
if (name.charAt(0) == '/') {
name = name.substring(1);
}
if (name.startsWith(packageDirName) && !entry.isDirectory() && name.endsWith(".class")) {
String className = name.substring(0, name.length() - 6).replace('/', '.');
try {
Class<?> clazz = Class.forName(className);
CLASS_CACHE.put(clazz.getSimpleName(), clazz);
} catch (ClassNotFoundException e) {
// 忽略无法加载的类
}
}
}
}
/**
* 清除缓存,重新初始化时使用
*/
public static synchronized void clearCache() {
CLASS_CACHE.clear();
initialized = false;
}
/**
* 获取缓存的类数量(用于调试)
*/
public static int getCachedClassCount() {
return CLASS_CACHE.size();
}
/**
* 获取所有缓存的类名(用于调试)
*/
public static Set<String> getCachedClassNames() {
return CLASS_CACHE.keySet();
}
}

View File

@@ -9,4 +9,8 @@
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
<update id="deleteByTemplateInstanceId" >
update BSE_TMPL_INSC_DAT set deleted = 1
WHERE INSC_ID = #{templateInstanceId}
</update>
</mapper>

View File

@@ -9,4 +9,12 @@
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
<!-- <delete id="deleteByTemplateInstanceId">-->
<!-- DELETE FROM bse_tmpl_insc_item-->
<!-- WHERE INSC_ID = #{templateInstanceId}-->
<!-- </delete>-->
<update id="deleteByTemplateInstanceId" >
update BSE_TMPL_INSC_ITM set deleted = 1
WHERE INSC_ID = #{templateInstanceId}
</update>
</mapper>