From 2137b938d61ef47276643308eec71b4e3ec531e8 Mon Sep 17 00:00:00 2001 From: dongzi Date: Wed, 10 Jun 2026 10:45:52 +0800 Subject: [PATCH] =?UTF-8?q?jar=E5=8C=85=E7=98=A6=E8=BA=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 7 +- .../common/WeComMarkdownSender.java | 43 ++++--- .../com/codechecker/notify/WeComNotifier.java | 49 +------ .../api-templates/api-method-change.md | 38 ++++++ .../classes/api-templates/api-param-change.md | 121 ++++++++++++++++++ .../classes/api-templates/api-path-change.md | 88 +++++++++++++ target/classes/notify-templates/README.md | 58 +++++++++ target/classes/notify-templates/dto.md | 106 +++++++++++++++ target/classes/notify-templates/entity.md | 49 +++++++ .../notify-templates/field-description.md | 57 +++++++++ target/classes/notify-templates/model.md | 49 +++++++ target/classes/notify-templates/vo.md | 63 +++++++++ 12 files changed, 658 insertions(+), 70 deletions(-) create mode 100644 target/classes/api-templates/api-method-change.md create mode 100644 target/classes/api-templates/api-param-change.md create mode 100644 target/classes/api-templates/api-path-change.md create mode 100644 target/classes/notify-templates/README.md create mode 100644 target/classes/notify-templates/dto.md create mode 100644 target/classes/notify-templates/entity.md create mode 100644 target/classes/notify-templates/field-description.md create mode 100644 target/classes/notify-templates/model.md create mode 100644 target/classes/notify-templates/vo.md diff --git a/pom.xml b/pom.xml index 6912686..a70cd76 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ com.github.javaparser - javaparser-symbol-solver-core + javaparser-core ${javaparser.version} @@ -27,11 +27,6 @@ snakeyaml 2.2 - - com.squareup.okhttp3 - okhttp - 4.12.0 - info.picocli picocli diff --git a/src/main/java/com/codechecker/common/WeComMarkdownSender.java b/src/main/java/com/codechecker/common/WeComMarkdownSender.java index 3d6c56c..2049db8 100644 --- a/src/main/java/com/codechecker/common/WeComMarkdownSender.java +++ b/src/main/java/com/codechecker/common/WeComMarkdownSender.java @@ -1,24 +1,20 @@ package com.codechecker.common; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; - import java.io.IOException; -import java.util.concurrent.TimeUnit; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; /** * 企微 Markdown 发送(与具体变更类型解耦)。 */ public class WeComMarkdownSender { private static final int MAX_LENGTH = 3800; - private static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); - private final OkHttpClient client = new OkHttpClient.Builder() - .connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(10, TimeUnit.SECONDS) + private final HttpClient client = HttpClient.newBuilder() + .connectTimeout(Duration.ofSeconds(10)) .build(); public boolean send(String webhookUrl, String content) { @@ -41,15 +37,26 @@ public class WeComMarkdownSender { String payload = "{\"msgtype\":\"markdown\",\"markdown\":{\"content\":" + jsonEscape(content) + "}}"; - Request request = new Request.Builder() - .url(webhookUrl) - .post(RequestBody.create(payload, JSON)) + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(webhookUrl)) + .timeout(Duration.ofSeconds(10)) + .header("Content-Type", "application/json; charset=utf-8") + .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); - try (Response response = client.newCall(request).execute()) { - if (response.isSuccessful() && response.body() != null) { - return response.body().string().contains("\"errcode\":0"); + try { + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + int statusCode = response.statusCode(); + if (statusCode >= 200 && statusCode < 300) { + String body = response.body(); + return body != null && body.contains("\"errcode\":0"); } - System.out.println("[错误] 企微返回异常: " + response.code()); + String body = response.body(); + System.out.println("[错误] 企微返回异常: " + statusCode + + (body != null ? " " + body : "")); + return false; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + System.out.println("[错误] 发送企微消息失败: " + e.getMessage()); return false; } catch (IOException e) { System.out.println("[错误] 发送企微消息失败: " + e.getMessage()); diff --git a/src/main/java/com/codechecker/notify/WeComNotifier.java b/src/main/java/com/codechecker/notify/WeComNotifier.java index e5085fa..f05dffe 100644 --- a/src/main/java/com/codechecker/notify/WeComNotifier.java +++ b/src/main/java/com/codechecker/notify/WeComNotifier.java @@ -1,18 +1,12 @@ package com.codechecker.notify; +import com.codechecker.common.WeComMarkdownSender; import com.codechecker.model.ApiEndpoint; import com.codechecker.model.ClassChangeReport; import com.codechecker.model.ClassType; import com.codechecker.model.FieldChange; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; -import java.io.IOException; import java.util.List; -import java.util.concurrent.TimeUnit; /** * 将 ClassChangeReport 渲染为企业微信 Markdown 并发送(或仅日志输出)。 @@ -22,12 +16,8 @@ import java.util.concurrent.TimeUnit; */ public class WeComNotifier { private static final int MAX_LENGTH = 3800; - private static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); - private final OkHttpClient client = new OkHttpClient.Builder() - .connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(10, TimeUnit.SECONDS) - .build(); + private final WeComMarkdownSender sender = new WeComMarkdownSender(); /** 逐条发送企微通知,返回成功条数 */ public int sendAll(String webhookUrl, List reports, String modifier, String modifyTime) { @@ -347,31 +337,7 @@ public class WeComNotifier { /** POST 企微 Webhook(markdown v1) */ private boolean postMarkdown(String webhookUrl, String content) { - if (webhookUrl == null || webhookUrl.isBlank() || webhookUrl.contains("YOUR_WECOM")) { - System.out.println("[警告] 未配置有效的企业微信 Webhook URL"); - System.out.println("--- 通知预览 ---"); - System.out.println(content.length() > 1000 ? content.substring(0, 1000) : content); - return false; - } - - String payload = "{\"msgtype\":\"markdown\",\"markdown\":{\"content\":" - + jsonEscape(content) + "}}"; - Request request = new Request.Builder() - .url(webhookUrl) - .post(RequestBody.create(payload, JSON)) - .build(); - try (Response response = client.newCall(request).execute()) { - if (response.isSuccessful() && response.body() != null) { - String body = response.body().string(); - return body.contains("\"errcode\":0"); - } - System.out.println("[错误] 企微返回异常: " + response.code() - + (response.body() != null ? " " + response.body().string() : "")); - return false; - } catch (IOException e) { - System.out.println("[错误] 发送企微消息失败: " + e.getMessage()); - return false; - } + return sender.send(webhookUrl, content); } /** 超长消息截断(企微上限 4096 字节 UTF-8) */ @@ -382,13 +348,4 @@ public class WeComNotifier { return text.substring(0, MAX_LENGTH) + "\n\n... 消息过长,已截断"; } - /** JSON 字符串转义 */ - private String jsonEscape(String text) { - String escaped = text - .replace("\\", "\\\\") - .replace("\"", "\\\"") - .replace("\n", "\\n") - .replace("\r", ""); - return "\"" + escaped + "\""; - } } diff --git a/target/classes/api-templates/api-method-change.md b/target/classes/api-templates/api-method-change.md new file mode 100644 index 0000000..bcbbdb8 --- /dev/null +++ b/target/classes/api-templates/api-method-change.md @@ -0,0 +1,38 @@ +# API 请求方式变更通知模版 + +对应 `11.py` → `build_method_change_markdown()`。 +适用:URI 不变,仅 **HTTP 方法** 变化(如 `GET` → `POST`)。 + +> 第一期是否纳入,待产品确认;模版先备齐。 + +--- + +## 完整示例 + +``` +# 【API请求方式变更通知】 + + 变更类型: **修改请求方式** + 路径: **jnpf-ftb/jnpf-ftb-biz/src/main/java/jnpf/workflow/controller/ApplyClockInController.java** + 修改人: dongzi + 修改时间: 2026-06-08 16:30:00 + +--------------------------------------- + +#### 【请求方式变更详情】 +- **URI:** **`/apply/clockIn/{id}`** +- **原请求方式:** **GET** +- **新请求方式:** **PUT****请求方式已变更** +``` + +--- + +## 检测逻辑 + +- 方法指纹相同 + URI 相同 + `httpMethod` 不同 → `is_method_changed = true` +- 与路径变更、参数变更报告**互斥拆分**(同 11.py `comparator` 约定) + +## 实现 + +- `EndpointDiffEngine` +- `ApiChangeNotifier.buildMethodChangeMarkdown()` diff --git a/target/classes/api-templates/api-param-change.md b/target/classes/api-templates/api-param-change.md new file mode 100644 index 0000000..18c5c16 --- /dev/null +++ b/target/classes/api-templates/api-param-change.md @@ -0,0 +1,121 @@ +# API 参数变更通知模版 + +对应 `11.py` → `build_markdown_notification()` 中参数变更分支 + `_format_endpoint_block()`。 +适用:**URI 与 HTTP 方法均未变**,仅入参发生变化。 + +--- + +## 完整示例 + +``` +# 【API参数变更通知】 +- **修改人:** dongzi +- **修改时间:** 2026-06-08 16:30:00 + +- **变更类型:** **修改参数** +- **URI:** **POST** `/apply/clockIn` +- **路径:** **jnpf-ftb/jnpf-ftb-biz/src/main/java/jnpf/workflow/controller/ApplyClockInController.java** + +--------------------------------------- + +#### 【接口参数变动详情】 + +**类对象变更(一级字段)** + +共 **1** 个类对象 · **2** 项字段变更 + +**`ApplyAttendanceChangeDto`** + +├─ `taskIds` · `List` · 必填 [新增] +> 说明:流程主键集合 +└─ `applyUser1` · `Integer` [删除] +> 说明:申请人员 + +**普通参数变更** + +共 **1** 项变更 + +1. `id` · `String` · 路径参数 [新增] +> 说明:主键 +``` + +--- + +## 示例(仅普通参数,无 RequestBody) + +``` +# 【API参数变更通知】 +- **修改人:** dongzi +- **修改时间:** 2026-06-08 16:30:00 + +- **变更类型:** **修改参数** +- **URI:** **GET** `/apply/clockIn/{id}` +- **路径:** **jnpf-ftb/.../ApplyClockInController.java** + +--------------------------------------- + +#### 【接口参数变动详情】 + +**普通参数变更** + +共 **1** 项变更 + +1. `pageSize` · `Integer` · 查询参数 [新增] +``` + +--- + +## 参数分类与检测 + +| 来源注解 | `source` 字段 | diff 粒度 | +|----------|---------------|-----------| +| `@RequestBody` | `body` | Dto **一级字段**(复用 `FieldDiffEngine`) | +| `@PathVariable` | `path` | 参数名、类型、增删 | +| `@RequestParam` | `query` | 参数名、类型、required、增删 | +| 无注解 | `simple` | 待确认是否纳入 | + +### 排除的框架参数(建议默认开启) + +`HttpServletRequest`、`HttpServletResponse`、`BindingResult`、`Principal`、`Authentication`、`Model`、`ModelMap`、`UriComponentsBuilder` 等。 + +--- + +## ParameterChange 数据结构(对齐 11.py) + +| 字段 | 说明 | +|------|------| +| `param_name` | 当前参数名 / 字段名 | +| `old_name` | 重命名前名称 | +| `param_type` | 类型字符串,如 `List` | +| `description` | 说明(@Schema / 注释) | +| `source` | `body` / `path` / `query` | +| `body_param_name` | `@RequestBody` 形参名 | +| `parent_dto` | Dto 简单类名 | +| `change_type` | `added` / `removed` / `modified` / `renamed` | +| `detail` | 类型变化等详情 | + +--- + +## 与路径变更的拆分规则(11.py 约定) + +| 同一次改动 | 通知策略 | +|------------|----------| +| 仅参数变 | 本模版 | +| 路径变 + 参数变 | **拆两条**:先路径通知,再参数通知 | +| 方法变 + 参数变 | **拆两条**:先方法通知,再参数通知 | +| 新增接口 + 带参数 | 路径通知可**附带**参数详情区块 | + +--- + +## JavaParser 实现要点 + +1. **EndpointSnapshotParser**:遍历 `MethodDeclaration.getParameters()`,读参数注解 +2. **@RequestBody**:取 Dto 类型 → `ClassFieldParser.parseFields()` 得字段列表 +3. **ParameterDiffEngine**:旧/新快照按方法指纹对齐后 diff +4. **ApiChangeNotifier**:渲染本模版;泛型类型展示规则与类变更通知一致(`<>` 不 HTML 转义) + +## 实现 + +- `ParameterDiffEngine` +- `ApiChangeNotifier.formatEndpointBlock()` +- 复用 `FieldDiffEngine` / `WeComNotifier` 中的字段行格式(可选统一) diff --git a/target/classes/api-templates/api-path-change.md b/target/classes/api-templates/api-path-change.md new file mode 100644 index 0000000..63f48db --- /dev/null +++ b/target/classes/api-templates/api-path-change.md @@ -0,0 +1,88 @@ +# API 路径变更通知模版 + +对应 `11.py` → `build_path_change_markdown()`。 +适用:**新增接口**、**删除接口**、**修改路径**。 + +--- + +## 完整示例(修改路径) + +``` +# 【API路径变更通知】 + + 变更类型: **修改路径** + 路径: **jnpf-ftb/jnpf-ftb-biz/src/main/java/jnpf/workflow/controller/ApplyClockInController.java** + 修改人: dongzi + 修改时间: 2026-06-08 16:30:00 + +--------------------------------------- + +#### 【URI变更详情】 +- **原路径:** ~~`/apply/clockIn`~~**旧路径** +- **新路径:** **`/apply/clockIn/v2`****新路径** +``` + +--- + +## 示例(新增接口) + +``` +# 【API路径变更通知】 + + 变更类型: **新增接口** + 路径: **jnpf-ftb/.../ApplyClockInController.java** + 修改人: dongzi + 修改时间: 2026-06-08 16:30:00 + +--------------------------------------- + +#### 【URI变更详情】 +- **原路径:** `-` +- **新路径:** **`/apply/clockIn`****新增** +``` + +> 若新增接口同时有参数变更,可在路径通知后追加【接口参数变动详情】区块(见 `api-param-change.md`)。 + +--- + +## 示例(删除接口) + +``` +# 【API路径变更通知】 + + 变更类型: **删除接口** + 路径: **jnpf-ftb/.../ApplyClockInController.java** + 修改人: dongzi + 修改时间: 2026-06-08 16:30:00 + +--------------------------------------- + +#### 【URI变更详情】 +- **原路径:** **`/apply/clockIn/{id}`****已删除** +- **新路径:** `已删除` +``` + +--- + +## 字段说明 + +| 占位符 | 来源 | +|--------|------| +| 变更类型 | `新增接口` / `删除接口` / `修改路径` | +| 路径 | Controller `.java` 相对仓库根路径(`source_file`) | +| 原路径 / 新路径 | 类级 `@RequestMapping` + 方法级 Mapping 拼接后的 URI | +| HTTP 方法 | 路径变更通知中默认不展示;与请求方式变更模版区分 | + +## 检测逻辑(JavaParser) + +1. 解析旧/新 commit 下同一 Controller 源码 AST +2. 提取每个方法的 `httpMethod` + `uri`(已有 `EndpointParser` 逻辑) +3. 用**方法指纹**(类文件 + 方法名,如 `ApplyClockInController.java#getApply`)匹配新旧接口;参数增删改由 ParameterDiffEngine 检测 +4. 指纹相同且 URI 不同 → **修改路径** +5. 仅旧有新无 → **删除**;仅新有旧无 → **新增** + +## 实现 + +- `EndpointSnapshotParser` — 解析快照 +- `EndpointDiffEngine` — 对比产出 `EndpointChangeReport.is_renamed_endpoint` 等标志 +- `ApiChangeNotifier.buildPathChangeMarkdown()` — 渲染本模版 diff --git a/target/classes/notify-templates/README.md b/target/classes/notify-templates/README.md new file mode 100644 index 0000000..86e10cc --- /dev/null +++ b/target/classes/notify-templates/README.md @@ -0,0 +1,58 @@ +# 类变更通知模版 + +Push 触发 CI 后,按变更类的后缀(`Dto` / `Vo` / `Entity` / `Model`)选用对应模版生成企业微信 Markdown 通知。 + +## 企微语法说明 + +使用 webhook **`markdown`**(v1),支持 font 三色;**不支持无序列表**,故各项以**引用块 + 换行**分行展示。 + +| 语法 | 说明 | +|------|------| +| `#` / `##` / `###` | 标题(主区块用【】) | +| `` `行内代码` `` | 字段名、URI | +| `>` | 引用行(每项一行) | +| `**bold**` | 头部四行、统计行加粗 | +| `` | 绿:类名、新增、HTTP 方法、新类型 | +| `` | 灰:说明、路径、无影响 | +| `` | 橙:[修改]/[删除]、旧类型、统计数字 | + +## 布局约定 + +1. **# 【类变更通知】** — 头部 4 项,每项一行 `>**标签: 值**`(加粗,冒号后两空格);变更对象括号内展示类中文说明(@Schema / Javadoc),无说明则仅类名 +2. **## 【对象变更细节】** — 统计行 + 每条变更单行(标签/说明/类型合并) +3. **## 【影响范围】** — 各 ### 小节内,每项一行引用 + +## 公共头部 + +``` +# 【类变更通知】 + +> **变更对象: ApplyAttendanceChangeDto流程表单 [出勤变更])** +> **修改人: dongzi** +> **时间: 2026-06-07 20:14:35** +> **路径: jnpf-ftb/.../ApplyAttendanceChangeDto.java** +``` + +## 影响范围 + +| 类类型 | request | response | 类转换 | +|--------|:-------:|:--------:|:------:| +| Dto | ✅ | ✅ | ✅ | +| Vo | ✅ | ✅ | ✅ | +| Entity / Model | ❌ | ❌ | ✅ | + +Dto/Vo 均固定展示 request、response 两栏;无匹配接口时显示「无」。类转换栏仅在 `dto_entity_conversion.enabled: true` 时展示,关闭时不出现该小节。实际影响由接口索引 + 嵌套关系传播,不假定 Dto 仅 request、Vo 仅 response。 + +## 模版文件 + +| 文件 | 场景 | +|------|------| +| [field-description.md](field-description.md) | 字段说明与行格式 | +| [dto.md](dto.md) | Dto | +| [vo.md](vo.md) | Vo | +| [entity.md](entity.md) | Entity | +| [model.md](model.md) | Model | + +## 实现 + +`WeComNotifier.buildMarkdown()` · 消息类型 `markdown` · 路径取自 `ClassChangeReport.sourceFile` diff --git a/target/classes/notify-templates/dto.md b/target/classes/notify-templates/dto.md new file mode 100644 index 0000000..b192bd2 --- /dev/null +++ b/target/classes/notify-templates/dto.md @@ -0,0 +1,106 @@ +# Dto 类变更通知模版 + +**识别规则**:类名以 `Dto` 结尾。 +**影响范围**:request + response + 类转换(无匹配时对应栏显示「无」)。 +**嵌套标识**:被其他 Dto/Vo 嵌套时在「变更对象」行追加 `(嵌套对象)`;若同时直接作接口入参/返回值根类型,再追加 `(顶层对象)`。纯顶层不标注。 + +--- + +## 完整示例(字段修改) + +``` +# 【类变更通知】 + +> **变更对象: ApplyAttendanceChangeDto流程表单 [出勤变更])** +> **修改人: dongzi** +> **时间: 2026-06-07 20:14:35** +> **路径: jnpf-ftb/jnpf-ftb-entity/src/main/java/jnpf/model/workflow/dto/ApplyAttendanceChangeDto.java** + +## 【对象变更细节】 + +> **共 4 项变更** + +> [修改] `taskId` 说明: 流程主键 类型: IntegerString + +> [修改] `changeUserId` 说明: 变更人员id 类型: StringInteger + +> [新增] `storeId` 说明: 门店ID 类型: String + +> [删除] `oldField` 说明: 已废弃字段 类型: Integer + +## 【影响范围】 + +### 影响 request 接口 +> POST `/apply/clockIn` +> PUT `/apply/clockIn/{id}` + +### 类转换影响 +> 未开启检测 +``` + +--- + +## 示例(嵌套对象) + +``` +> **变更对象: UserSelfDto嵌套对象)** +``` + +若该类同时直接出现在某接口 `@RequestBody` 或返回值类型中: + +``` +> **变更对象: SomeDto说明)(嵌套对象)(顶层对象)** +``` + +--- + +## 示例(类删除) + +``` +## 【对象变更细节】 + +> [已删除] 该类文件已被移除 +``` + +--- + +## 示例(仅类名变更) + +``` +## 【对象变更细节】 + +> [类名变更] ApplyAttendanceChangeDtoApplyAttendanceChangeNewDto +> 字段无变化 + +## 【影响范围】 + +### 影响 request 接口 +> POST `/apply/clockIn` +> PUT `/apply/clockIn/{id}` + +### 类转换影响 +> 未开启检测 +``` + +--- + +## 示例(类名 + 字段同时变更) + +``` +## 【对象变更细节】 + +> [类名变更] ApplyAttendanceChangeDtoApplyAttendanceChangeNewDto + +> **共 1 项变更** + +> [修改] `changeMinute` 说明: 变更分钟数 类型: IntegerString +``` + +--- + +## 占位符 + +| 占位符 | 来源 | +|--------|------| +| 路径 | Git 相对路径,`ClassChangeReport.sourceFile` | +| 说明 | `@Schema` / 注释 | diff --git a/target/classes/notify-templates/entity.md b/target/classes/notify-templates/entity.md new file mode 100644 index 0000000..77e8e8a --- /dev/null +++ b/target/classes/notify-templates/entity.md @@ -0,0 +1,49 @@ +# Entity 类变更通知模版 + +**识别规则**:类名以 `Entity` 结尾。 +**影响范围**:仅类转换(不展示 request/response 接口)。 + +--- + +## 完整示例(字段修改) + +``` +# 【类变更通知】 + +> **变更对象: TrainingPositionEntity培训岗位)** +> **修改人: 张三** +> **时间: 2026-06-07 14:30:00** +> **路径: jnpf-ftb/jnpf-ftb-entity/src/main/java/jnpf/entity/training/TrainingPositionEntity.java** + +## 【对象变更细节】 + +> **共 1 项变更** + +> [修改] `createTime` 说明: 创建时间 类型: DateLocalDateTime + +## 【影响范围】 + +### 类转换影响 +> Entity: TrainingPositionEntity +``` + +--- + +## 示例(类删除) + +``` +## 【对象变更细节】 + +> [已删除] 该类文件已被移除 +``` + +--- + +## 示例(仅类名变更) + +``` +## 【对象变更细节】 + +> [类名变更] TrainingPositionEntityTrainingPositionNewEntity +> 字段无变化 +``` diff --git a/target/classes/notify-templates/field-description.md b/target/classes/notify-templates/field-description.md new file mode 100644 index 0000000..9243b29 --- /dev/null +++ b/target/classes/notify-templates/field-description.md @@ -0,0 +1,57 @@ +# 字段说明规则 + +字段变更采用 **引用块 + 单行合并 + font 颜色**,遵循企微 `markdown` v1(不支持列表)。 + +## 说明提取优先级 + +| 优先级 | 来源 | +|:------:|------| +| 1 | `@Schema(description = "...")` | +| 2 | `@ApiModelProperty` | +| 3 | `/** ... */` 字段注释 | +| 4 | 空串 | + +## 字段变更行格式 + +每条变更占**一行**,标签、说明、类型横向排列,冒号后两空格: + +``` +> **共 2 项变更** + +> [重命名] taskIdtaskIds 说明: 流程主键 + +> [新增] `applyUserList` 说明: 申请人员集合 类型: List + +> [删除] `applyUser1` 说明: 申请人员 类型: Integer +``` + +| 操作 | 标签 | 类型段 | +|------|------|--------| +| 新增 | info `[新增]` | 始终展示,绿色 `info` | +| 删除 | warning `[删除]` | 始终展示,橙色 `warning` | +| 修改 | warning `[修改]` | 始终展示,旧类型 warning → 新类型 info | +| 重命名 | warning `[重命名]` | 始终展示;仅改名时单色 info,改类型时 old → new | + +### 重命名配对规则 + +- 删除+新增且**类型相同、说明相同**(非空)→ `[重命名]` +- 删除+新增且**说明相同但类型不同** → `[重命名]` + 类型行 +- 说明均为空时也可配对 +- 说明不同则不配对,保持删除+新增 + +- 统计行加粗,数字用 warning(橙色),文案为「共 N 项变更」(不含「字段」) +- 多条变更之间用**空行**分隔 +- 说明为空时显示 `(无说明)` +- 头部四行加粗,用 `quoteKvBold`;不要在 `` 内嵌 `**bold**` + +## 接口行格式 + +``` +> POST `/apply/clockIn` +``` + +## 实现 + +- `ClassFieldParser.extractFieldLabel()` +- `FieldDiffEngine` — 类型变化产生 `[修改]`,说明匹配的删除+新增合并为 `[重命名]` +- `WeComNotifier.formatFieldChange()` diff --git a/target/classes/notify-templates/model.md b/target/classes/notify-templates/model.md new file mode 100644 index 0000000..cc93d4d --- /dev/null +++ b/target/classes/notify-templates/model.md @@ -0,0 +1,49 @@ +# Model 类变更通知模版 + +**识别规则**:类名以 `Model` 结尾。 +**影响范围**:仅类转换(不展示 request/response 接口)。 + +--- + +## 完整示例(字段修改) + +``` +# 【类变更通知】 + +> **变更对象: AttendanceRuleModel考勤规则)** +> **修改人: 张三** +> **时间: 2026-06-07 14:30:00** +> **路径: jnpf-ftb/jnpf-ftb-entity/src/main/java/jnpf/model/attendance/AttendanceRuleModel.java** + +## 【对象变更细节】 + +> **共 1 项变更** + +> [修改] `ruleType` 说明: 规则类型 类型: DateString + +## 【影响范围】 + +### 类转换影响 +> Entity: AttendanceRuleEntity +``` + +--- + +## 示例(类删除) + +``` +## 【对象变更细节】 + +> [已删除] 该类文件已被移除 +``` + +--- + +## 示例(仅类名变更) + +``` +## 【对象变更细节】 + +> [类名变更] AttendanceRuleModelAttendanceRuleNewModel +> 字段无变化 +``` diff --git a/target/classes/notify-templates/vo.md b/target/classes/notify-templates/vo.md new file mode 100644 index 0000000..1289030 --- /dev/null +++ b/target/classes/notify-templates/vo.md @@ -0,0 +1,63 @@ +# Vo 类变更通知模版 + +**识别规则**:类名以 `Vo` 或 `VO` 结尾。 +**影响范围**:request + response + 类转换(无匹配时对应栏显示「无」)。 +**嵌套标识**:规则同 Dto——仅嵌套时标注 `(嵌套对象)`,嵌套且直接作接口根类型时追加 `(顶层对象)`。 + +--- + +## 完整示例(字段修改) + +``` +# 【类变更通知】 + +> **变更对象: AttendanceDetailVo考勤详情)** +> **修改人: 张三** +> **时间: 2026-06-07 14:30:00** +> **路径: jnpf-ftb/jnpf-ftb-entity/src/main/java/jnpf/model/attendance/vo/AttendanceDetailVo.java** + +## 【对象变更细节】 + +> **共 2 项变更** + +> [新增] `overtimeHours` 说明: 加班时长 + +> [修改] `status` 说明: 考勤状态 类型: IntegerString + +## 【影响范围】 + +### 影响 response 接口 +> GET `/api/attendance/detail` + +### 类转换影响 +> Entity: AttendanceDetailEntity +``` + +--- + +## 示例(类删除) + +``` +## 【对象变更细节】 + +> [已删除] 该类文件已被移除 +``` + +--- + +## 示例(仅类名变更) + +``` +## 【对象变更细节】 + +> [类名变更] AttendanceDetailVoAttendanceDetailNewVo +> 字段无变化 + +## 【影响范围】 + +### 影响 response 接口 +> GET `/api/attendance/detail` + +### 类转换影响 +> 未开启检测 +```