diff --git a/.gitea/checker/notify-templates/README.md b/.gitea/checker/notify-templates/README.md index d81368e..38eee78 100644 --- a/.gitea/checker/notify-templates/README.md +++ b/.gitea/checker/notify-templates/README.md @@ -18,7 +18,7 @@ Push 触发 CI 后,按变更类的后缀(`Dto` / `Vo` / `Entity` / `Model` ## 布局约定 -1. **# 【类变更通知】** — 头部 4 项,每项一行 `>**标签: 值**`(加粗,冒号后两空格) +1. **# 【类变更通知】** — 头部 4 项,每项一行 `>**标签: 值**`(加粗,冒号后两空格);变更对象括号内展示类中文说明(@Schema / Javadoc),无说明则仅类名 2. **## 【对象变更细节】** — 统计行 + 每条变更单行(标签/说明/类型合并) 3. **## 【影响范围】** — 各 ### 小节内,每项一行引用 @@ -27,7 +27,7 @@ Push 触发 CI 后,按变更类的后缀(`Dto` / `Vo` / `Entity` / `Model` ``` # 【类变更通知】 -> **变更对象: ApplyAttendanceChangeDto(Dto)** +> **变更对象: ApplyAttendanceChangeDto流程表单 [出勤变更])** > **修改人: dongzi** > **时间: 2026-06-07 20:14:35** > **路径: jnpf-ftb/.../ApplyAttendanceChangeDto.java** diff --git a/.gitea/checker/notify-templates/dto.md b/.gitea/checker/notify-templates/dto.md index 8598477..ebcb2d4 100644 --- a/.gitea/checker/notify-templates/dto.md +++ b/.gitea/checker/notify-templates/dto.md @@ -10,7 +10,7 @@ ``` # 【类变更通知】 -> **变更对象: ApplyAttendanceChangeDto(Dto)** +> **变更对象: ApplyAttendanceChangeDto流程表单 [出勤变更])** > **修改人: dongzi** > **时间: 2026-06-07 20:14:35** > **路径: jnpf-ftb/jnpf-ftb-entity/src/main/java/jnpf/model/workflow/dto/ApplyAttendanceChangeDto.java** diff --git a/.gitea/checker/notify-templates/entity.md b/.gitea/checker/notify-templates/entity.md index 9ddd1a9..77e8e8a 100644 --- a/.gitea/checker/notify-templates/entity.md +++ b/.gitea/checker/notify-templates/entity.md @@ -10,7 +10,7 @@ ``` # 【类变更通知】 -> **变更对象: TrainingPositionEntity(Entity)** +> **变更对象: TrainingPositionEntity培训岗位)** > **修改人: 张三** > **时间: 2026-06-07 14:30:00** > **路径: jnpf-ftb/jnpf-ftb-entity/src/main/java/jnpf/entity/training/TrainingPositionEntity.java** diff --git a/.gitea/checker/notify-templates/model.md b/.gitea/checker/notify-templates/model.md index eabb659..cc93d4d 100644 --- a/.gitea/checker/notify-templates/model.md +++ b/.gitea/checker/notify-templates/model.md @@ -10,7 +10,7 @@ ``` # 【类变更通知】 -> **变更对象: AttendanceRuleModel(Model)** +> **变更对象: AttendanceRuleModel考勤规则)** > **修改人: 张三** > **时间: 2026-06-07 14:30:00** > **路径: jnpf-ftb/jnpf-ftb-entity/src/main/java/jnpf/model/attendance/AttendanceRuleModel.java** diff --git a/.gitea/checker/notify-templates/vo.md b/.gitea/checker/notify-templates/vo.md index c5a1c55..02c8a10 100644 --- a/.gitea/checker/notify-templates/vo.md +++ b/.gitea/checker/notify-templates/vo.md @@ -10,7 +10,7 @@ ``` # 【类变更通知】 -> **变更对象: AttendanceDetailVo(Vo)** +> **变更对象: AttendanceDetailVo考勤详情)** > **修改人: 张三** > **时间: 2026-06-07 14:30:00** > **路径: jnpf-ftb/jnpf-ftb-entity/src/main/java/jnpf/model/attendance/vo/AttendanceDetailVo.java** diff --git a/.gitea/checker/src/main/java/com/autoCheck/analyzer/ClassChangeAnalyzer.java b/.gitea/checker/src/main/java/com/autoCheck/analyzer/ClassChangeAnalyzer.java index b22ae06..f9e539f 100644 --- a/.gitea/checker/src/main/java/com/autoCheck/analyzer/ClassChangeAnalyzer.java +++ b/.gitea/checker/src/main/java/com/autoCheck/analyzer/ClassChangeAnalyzer.java @@ -56,13 +56,17 @@ public class ClassChangeAnalyzer { String path = changedFile.getRelativePath(); String oldSource = gitScanner.readFileAtCommit(oldSha, path); + String classDescription = classDeclParser.extractClassDescription( + oldSource, changedFile.getClassName()); + ClassChangeReport report = new ClassChangeReport( changedFile.getClassName(), null, changedFile.getClassType(), ClassChangeKind.DELETED, path, - config.isDtoEntityConversionEnabled() + config.isDtoEntityConversionEnabled(), + classDescription ); impactAnalyzer.analyze(report, endpointIndex, config, repoRoot, oldSource, oldSource); return report; @@ -105,13 +109,16 @@ public class ClassChangeAnalyzer { return null; } + String classDescription = classDeclParser.extractClassDescription(newSource, newClassName); + ClassChangeReport report = new ClassChangeReport( newClassName, renamed ? oldClassName : null, changedFile.getClassType(), changeKind, newPath, - config.isDtoEntityConversionEnabled() + config.isDtoEntityConversionEnabled(), + classDescription ); fieldChanges.forEach(report::addFieldChange); impactAnalyzer.analyze(report, endpointIndex, config, repoRoot, newSource, oldSource); diff --git a/.gitea/checker/src/main/java/com/autoCheck/model/ClassChangeReport.java b/.gitea/checker/src/main/java/com/autoCheck/model/ClassChangeReport.java index 70e1fc8..2f47c4d 100644 --- a/.gitea/checker/src/main/java/com/autoCheck/model/ClassChangeReport.java +++ b/.gitea/checker/src/main/java/com/autoCheck/model/ClassChangeReport.java @@ -12,6 +12,7 @@ public class ClassChangeReport { private final ClassType classType; private final ClassChangeKind changeKind; private final String sourceFile; + private final String classDescription; private final List fieldChanges = new ArrayList<>(); private final List inputImpactEndpoints = new ArrayList<>(); private final List conversionEntities = new ArrayList<>(); @@ -20,13 +21,14 @@ public class ClassChangeReport { public ClassChangeReport(String className, String oldClassName, ClassType classType, ClassChangeKind changeKind, String sourceFile, - boolean conversionCheckEnabled) { + boolean conversionCheckEnabled, String classDescription) { this.className = className; this.oldClassName = oldClassName; this.classType = classType; this.changeKind = changeKind; this.sourceFile = sourceFile; this.conversionCheckEnabled = conversionCheckEnabled; + this.classDescription = classDescription == null ? "" : classDescription.trim(); } /** 当前(新)简单类名 */ @@ -62,6 +64,11 @@ public class ClassChangeReport { return sourceFile; } + /** 类级中文说明(@Schema / 类 Javadoc),无则空串 */ + public String getClassDescription() { + return classDescription; + } + /** 是否整文件删除 */ public boolean isDeleted() { return changeKind == ClassChangeKind.DELETED; diff --git a/.gitea/checker/src/main/java/com/autoCheck/notify/WeComNotifier.java b/.gitea/checker/src/main/java/com/autoCheck/notify/WeComNotifier.java index f68d9d0..c46b195 100644 --- a/.gitea/checker/src/main/java/com/autoCheck/notify/WeComNotifier.java +++ b/.gitea/checker/src/main/java/com/autoCheck/notify/WeComNotifier.java @@ -82,11 +82,20 @@ public class WeComNotifier { return truncate(sb.toString()); } + /** 变更对象行:类名(绿)+ 可选中文说明(灰,整行加粗) */ + private String formatChangeTarget(ClassChangeReport report) { + String name = colorInfo(safe(report.getClassName())); + String description = report.getClassDescription(); + if (description == null || description.isBlank()) { + return name; + } + return name + "(" + colorComment(description) + ")"; + } + /** 头部元信息,每项一行引用(加粗) */ private void appendHeader(StringBuilder sb, ClassChangeReport report, String modifier, String modifyTime) { - sb.append(quoteKvBold("变更对象", colorInfo(safe(report.getClassName())) - + "(" + report.getClassType().getLabel() + ")")).append("\n"); + sb.append(quoteKvBold("变更对象", formatChangeTarget(report))).append("\n"); sb.append(quoteKvBold("修改人", colorComment(modifier))).append("\n"); sb.append(quoteKvBold("时间", colorComment(modifyTime))).append("\n"); sb.append(quoteKvBold("路径", colorComment(report.getSourceFile()))).append("\n"); diff --git a/.gitea/checker/src/main/java/com/autoCheck/parser/ClassDeclParser.java b/.gitea/checker/src/main/java/com/autoCheck/parser/ClassDeclParser.java index d01df8a..f8ed0c3 100644 --- a/.gitea/checker/src/main/java/com/autoCheck/parser/ClassDeclParser.java +++ b/.gitea/checker/src/main/java/com/autoCheck/parser/ClassDeclParser.java @@ -4,9 +4,16 @@ import com.github.javaparser.StaticJavaParser; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.TypeDeclaration; +import com.github.javaparser.ast.comments.JavadocComment; +import com.github.javaparser.ast.expr.AnnotationExpr; +import com.github.javaparser.ast.expr.Expression; +import com.github.javaparser.ast.expr.NormalAnnotationExpr; +import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr; + +import java.util.Optional; /** - * 从 Java 源文件路径或 AST 解析类名(简单名 / 全限定名)。 + * 从 Java 源文件路径或 AST 解析类名(简单名 / 全限定名)及类级中文说明。 */ public class ClassDeclParser { @@ -60,6 +67,100 @@ public class ClassDeclParser { return inferQualifiedFromPath(relativePath, simpleName); } + /** + * 提取类级中文说明:@Schema(description/title) > 类 Javadoc 首段。 + */ + public String extractClassDescription(String source, String expectedClassName) { + if (source == null || source.isBlank()) { + return ""; + } + try { + CompilationUnit cu = StaticJavaParser.parse(source); + ClassOrInterfaceDeclaration classDecl = findClass(cu, expectedClassName); + if (classDecl == null) { + return ""; + } + String fromSchema = readSchemaDescription(classDecl); + if (!fromSchema.isEmpty()) { + return fromSchema; + } + return extractClassJavadoc(classDecl); + } catch (Exception ignored) { + return ""; + } + } + + private ClassOrInterfaceDeclaration findClass(CompilationUnit cu, String expectedClassName) { + if (expectedClassName != null && !expectedClassName.isBlank()) { + for (TypeDeclaration type : cu.getTypes()) { + if (type instanceof ClassOrInterfaceDeclaration) { + ClassOrInterfaceDeclaration classDecl = (ClassOrInterfaceDeclaration) type; + if (classDecl.getNameAsString().equals(expectedClassName)) { + return classDecl; + } + } + } + } + for (TypeDeclaration type : cu.getTypes()) { + if (type instanceof ClassOrInterfaceDeclaration) { + return (ClassOrInterfaceDeclaration) type; + } + } + return null; + } + + private String readSchemaDescription(ClassOrInterfaceDeclaration classDecl) { + for (AnnotationExpr annotation : classDecl.getAnnotations()) { + if (!"Schema".equals(annotation.getNameAsString())) { + continue; + } + String description = readAnnotationStringValue(annotation, "description"); + if (!description.isEmpty()) { + return description; + } + String title = readAnnotationStringValue(annotation, "title"); + if (!title.isEmpty()) { + return title; + } + } + return ""; + } + + private String readAnnotationStringValue(AnnotationExpr annotation, String attributeName) { + if (annotation.isNormalAnnotationExpr()) { + NormalAnnotationExpr normal = annotation.asNormalAnnotationExpr(); + for (var pair : normal.getPairs()) { + if (pair.getNameAsString().equals(attributeName)) { + return literalString(pair.getValue()); + } + } + return ""; + } + if (annotation.isSingleMemberAnnotationExpr()) { + SingleMemberAnnotationExpr single = annotation.asSingleMemberAnnotationExpr(); + if ("value".equals(attributeName) || "description".equals(attributeName)) { + return literalString(single.getMemberValue()); + } + } + return ""; + } + + private String literalString(Expression expression) { + if (expression.isStringLiteralExpr()) { + return expression.asStringLiteralExpr().getValue().trim(); + } + return ""; + } + + private String extractClassJavadoc(ClassOrInterfaceDeclaration classDecl) { + Optional javadoc = classDecl.getJavadocComment(); + if (javadoc.isEmpty()) { + return ""; + } + String text = javadoc.get().parse().getDescription().toText(); + return text == null ? "" : text.trim().replaceAll("\\s+", " "); + } + /** 从 src/main/java/ 后的路径推断 package.className */ public static String inferQualifiedFromPath(String relativePath, String className) { if (relativePath == null || relativePath.isBlank()) {