From cf06dc6afc5ee2f2dc9bed05764d3f31e5290061 Mon Sep 17 00:00:00 2001 From: API Changelog Bot Date: Sat, 16 May 2026 14:16:12 +0800 Subject: [PATCH] =?UTF-8?q?docs(product-v2):=20=E6=93=8D=E4=BD=9C=E6=97=A5?= =?UTF-8?q?=E5=BF=97=20P1=20=E9=80=90=E6=97=A5=E8=81=9A=E5=90=88=20diff=20?= =?UTF-8?q?+=20=E8=B7=A8=E4=BA=A7=E5=93=81=E6=A3=80=E7=B4=A2=20(PR=20#2423?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 (1M context) --- ...uct_v2_operation_log_p1_aggregated_diff.md | 172 ++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 changelogs/2026-05/16_feat_product_v2_operation_log_p1_aggregated_diff.md diff --git a/changelogs/2026-05/16_feat_product_v2_operation_log_p1_aggregated_diff.md b/changelogs/2026-05/16_feat_product_v2_operation_log_p1_aggregated_diff.md new file mode 100644 index 0000000..1fd5b72 --- /dev/null +++ b/changelogs/2026-05/16_feat_product_v2_operation_log_p1_aggregated_diff.md @@ -0,0 +1,172 @@ +# product-v2: 操作日志 P1 — 价格日历逐日聚合 diff + STEP2-5 全字段 + 跨产品检索 + +> **服务**: hl-product-service-v2 (端口 8083) +> **PR**: #2423(承接 P0 #2355) +> **Issue**: #2409 +> **日期**: 2026-05-16 +> **影响范围**: 管理端「产品 → 操作日志」侧边栏 + 新增「跨产品操作日志检索」入口 + +--- + +## ⚠️ 关键变化 + +**P0 已让 `changes` 字段可用,P1 让 `changes` 真正"细到每天每档"+ 全字段覆盖**: + +- 旧逻辑(P0 上线后):PRICE_SET 只看到 1 行「成人售价 5800→9400」,不知道改了哪几天 +- 新逻辑(P1):**按 (字段, 档位, 旧值, 新值) 智能聚合日期** → 8 天改同价 = **1 行带日期范围**「成人售价 2026-07-12~07-19 (8 天) 经典档: 5800→9400」 +- **前端 0 改动**:复用 P0 的 `changes` 数组渲染表格,新 `fieldLabel` 自带聚合描述 + +**新接口**:`GET /admin/product/item/operation-logs/search` 跨产品按字段名检索(运营查"今天谁改过价")。 + +--- + +## 一、背景 + +承接 P0 [#2355](https://git.1814.love:8443/wx/HL/pulls/2355) — 张老板查产品改价时,P0 只能看到「成人售价 5800→9400」一行(取第一天作代表),看不出来"是哪几天改了"。如果运营改 8 天里 3 天,剩 5 天没改,P0 完全无法区分。 + +P1 解决:逐日 diff + 智能聚合 + STEP2-5 全字段全覆盖。 + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 查产品操作日志 | GET | `/admin/product/item/{id}/operation-logs` | **出参增强** | `changes` 数组含聚合 fieldLabel + STEP2-5 全字段 | +| 2 | 跨产品检索操作日志 | GET | `/admin/product/item/operation-logs/search` | **新接口** | 按字段名(如 adultSellPrice)查谁改过价 | + +--- + +## 三、接口详情 + +### 1. 查产品操作日志(出参增强) + +`changes[].fieldLabel` 现在自带日期范围描述: + +```json +{ + "action": "PRICE_SET", + "actionLabel": "设置价格", + "step": "STEP4", + "stepLabel": "价格与班期", + "changes": [ + { + "field": "adultSellPrice", + "fieldLabel": "成人售价 2026-07-12~07-19 (8 天) 经典档", + "oldValue": "5800", + "newValue": "9400", + "changeType": "MODIFY" + }, + { + "field": "childSellPrice", + "fieldLabel": "儿童售价 2026-07-12~07-19 (8 天) 经典档", + "oldValue": "3000", + "newValue": "3980", + "changeType": "MODIFY" + } + ] +} +``` + +#### 聚合描述格式 + +| 场景 | fieldLabel 示例 | +|------|----------------| +| 连续日期 | `成人售价 2026-07-12~07-19 (8 天) 经典档` | +| 离散日期 | `成人售价 2026-07-12, 07-15, 07-18 (3 天) 经典档` | +| 单天 | `成人售价 2026-07-12 经典档` | +| 跨月连续 | `成人售价 2026-07-30~08-01 (3 天) 经典档` | +| 不同新值(如周末加价) | 自动按 oldValue→newValue 分多组,多行 | + +#### 长文本字段(>200 字)摘要 + +```json +{ + "field": "introduction", + "fieldLabel": "产品介绍", + "oldValue": "已修改 (前80字…后80字)", + "newValue": "已修改 (前80字…后80字)", + "oldHash": "a3f4...", + "newHash": "b8e2...", + "changeType": "MODIFY" +} +``` +- 字段白名单:`description / introduction / highlights / quickUnderstand / childExperience / growthGains / equipmentList / routeMapUrl / detailContent / coverContent` +- `oldHash/newHash`:SHA-256 前 16 字节,**前端可选展示**(用于跨日志判断"内容是否真变了") + +#### 集合字段聚合 + +```json +{ + "field": "itineraryDays", + "fieldLabel": "行程列表", + "oldValue": "共 7 天", + "newValue": "共 8 天 (新增 1 / 删除 0)", + "changeType": "MODIFY" +} +``` +- 集合白名单:`seasons / tags / tiers / itineraryDays / dayNodes / dayHotels / feeItems / carouselImages / excludedFees / includedFees / customFees` +- ⚠️ **注意**:集合字段不做深 diff(避免日志 JSON 爆 50KB+),只聚合「新增 N / 删除 M」。具体哪一项的字段变了,目前需要查日志详情(P2 后续可优化) + +--- + +### 2. 跨产品检索操作日志(新接口) + +`GET /admin/product/item/operation-logs/search` + +#### 入参(VO) + +| 字段 | 位置 | 类型 | 必填 | 默认 | 说明 | +|------|------|------|------|------|------| +| `field` | Query | String | ✅ | — | 字段英文名,如 `adultSellPrice` | +| `fromDate` | Query | LocalDate | ❌ | today-30d | 开始日期(双侧空时套 30 天兜底) | +| `toDate` | Query | LocalDate | ❌ | today | 结束日期 | +| `page` | Query | Integer | ❌ | 1 | 页码 | +| `size` | Query | Integer | ❌ | 20 (max 100) | 页大小 | + +#### 权限 + +Service 入口校验 role ∈ {`SUPER_ADMIN`, `ADMIN`},普通销售员调用返 `PERMISSION_DENIED`(403 业务码)。 + +#### 全词匹配 + +避免 `field=price` 误命中 `adultSellPrice` / `childSellPrice` / `infantPrice`: +- 写入端:`changed_fields` 存 `,adultSellPrice,childSellPrice,`(两端逗号包裹) +- 查询端:`LIKE '%,adultSellPrice,%'` 全词匹配 +- 兼容老日志:P0 写入的没逗号包裹,OR 兜底 3 种边界(exact / 头部 / 尾部) + +#### 出参 + +复用 `ProductOperationLogRespVO`(带分页)。 + +--- + +## 四、前端改动建议(mmg) + +**方案 A+ 聚合版**:**前端 0 改动**。 + +- P0 已实现的 `changes` 表格渲染逻辑自动适配(新 fieldLabel 自带"日期范围 (N 天) 档位名") +- 长文本字段:oldValue/newValue 已是「已修改 (前80字…后80字)」文本,直接渲染 +- 集合字段:oldValue/newValue 已是「共 N 条 (新增 A / 删除 C)」文本,直接渲染 + +**新接口入口建议**(可选):管理端加个「操作日志检索」菜单,调 `/operation-logs/search?field=&fromDate=&toDate=`,用于审计场景。 + +--- + +## 五、向后兼容 + +- ✅ 老日志(changes=null)继续不渲染 diff 区块 +- ✅ P0 写入的日志(changed_fields 没两端逗号)依然能被新检索接口匹配 +- ✅ 新接口 `/operation-logs/search` 不影响现有 `/operation-logs` +- ✅ Flyway V20260516_003 只加索引,无 DDL 风险 + +**部署顺序**:Flyway 先行 → 后端发布。前端 0 改动可选发。 + +--- + +## 六、不在本期范围(P2 后续) + +- **集合字段深 diff**:当前只聚合「新增/删除数」,不展示哪一项的哪个字段变了 +- 「还原到此版本」按钮 +- 调价超阈值(>20%)钉钉/企微告警 +- 跨产品聚合可视化页(直接读 `/operation-logs/search` 即可)