feat(review): 评价模块迁移到 order-v2 服务(URL 不变 / 状态机对照 / Feign 链路变化)
这个提交包含在:
父节点
8ad5d0638d
当前提交
a04916e04c
@ -0,0 +1,230 @@
|
||||
# 评价模块迁移到 order-v2 服务(URL 不变 / 状态机对照 / Feign 链路变化)
|
||||
|
||||
> **日期**:2026-04-21
|
||||
> **服务**:`hl-user-service` → `hl-order-service`(v2)
|
||||
> **PR**:#1130(merge commit `cff993d12e3eb33f8c19d14bb18a9de001f5f971`)
|
||||
> **类型**:后端跨服务迁移 / 重构
|
||||
> **前端调用影响**:✅ **REST 路径零变化,前端无需改代码**(本 changelog 只是告知 + 状态机对照,防止有硬编码状态常量踩坑)
|
||||
|
||||
---
|
||||
|
||||
## 一、变更总览
|
||||
|
||||
评价(review)模块从 **hl-user-service** 整体搬到 **hl-order-service-v2**。
|
||||
|
||||
- **网关路由已同步切换**:`/admin/review/**` 原先由 gateway 转 `lb://hl-user-service`,现在转 `lb://hl-order-service`。前端用原 URL 直接调就行
|
||||
- **BFF(hl-mp-service)Feign 内部目标服务切换**:`MpReviewFeignClient(name="hl-user-service")` → `name="hl-order-service"`,小程序前端调 `/mp/review/**` 完全无感
|
||||
- **DB 真实表**从 `hl_user_service` / `hl_review_service`(VIEW + 废弃库)搬到 `hl_order_service_v2`
|
||||
- **评价审核 5 状态 + 6 事件** 改用 cola 状态机(原先是 if-else 散写)
|
||||
|
||||
---
|
||||
|
||||
## 二、受影响的 URL(全部路径不变)
|
||||
|
||||
### 管理端(hl-ui)— 7 个 `/admin/review/**`
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| GET | `/admin/review/list` | 评价列表(分页) |
|
||||
| GET | `/admin/review/{reviewId}` | 评价详情 |
|
||||
| POST | `/admin/review/{reviewId}/approve` | 人工审核通过 |
|
||||
| POST | `/admin/review/{reviewId}/reject` | 人工审核拒绝 |
|
||||
| POST | `/admin/review/{reviewId}/override-approve` | 覆盖通过(机审拒绝后管理员放行) |
|
||||
| POST | `/admin/review/{reviewId}/reply` | 管理员回复 |
|
||||
| PUT | `/admin/review/{reviewId}/keyword-tags` | 编辑评价关键词标签 |
|
||||
|
||||
### 小程序端(hl-mp)— 14 个 `/mp/review/**` + 3 个 `/mp/like/**`
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| GET | `/mp/review/rating-categories` | 评分类别字典 |
|
||||
| GET | `/mp/review/filter-tags` | 过滤标签(支持 productCategory) |
|
||||
| POST | `/mp/review/create` | 创建评价 |
|
||||
| GET | `/mp/review/my` | 我的评价列表 |
|
||||
| GET | `/mp/review/search` | 搜索评价 |
|
||||
| GET | `/mp/review/target` | 按目标查(productId/customizerId 等) |
|
||||
| GET | `/mp/review/product/{productId}` | 产品评价列表 |
|
||||
| GET | `/mp/review/product/{productId}/highlights` | 产品精选好评 |
|
||||
| GET | `/mp/review/stats` | 评价统计(平均分/好评率) |
|
||||
| GET | `/mp/review/featured` | 首页/列表精选评价 |
|
||||
| GET | `/mp/review/order/{orderId}/reviewed` | 订单是否已评价 |
|
||||
| GET | `/mp/review/order/{orderId}/reviewable-targets` | 订单可评价目标列表 |
|
||||
| POST | `/mp/review/{reviewId}/like` | 点赞 |
|
||||
| GET | `/mp/review/{reviewId}/like/check` | 查询是否已点赞 |
|
||||
| POST | `/mp/like/*`(3 个) | 透调评价点赞 Feign |
|
||||
|
||||
### 其它端点(无变化)
|
||||
|
||||
- 订单详情里"是否已评价"标记 `orders.is_reviewed`:由后端同事务内强一致更新(原本是 Feign + afterCommit 最终一致),前端字段取法不变
|
||||
- 评价图片/视频 OSS 链接字段 `images[].imageUrl` / `videos[].videoUrl`:位置、命名、协议不变
|
||||
|
||||
---
|
||||
|
||||
## 三、⚠️ 状态机改造 — 前端请核对硬编码状态常量
|
||||
|
||||
评价审核状态机重新梳理,**旧状态值有变**。如果前端存在状态字符串硬编码(status 字段 switch/判断),**必须参考下表确认取值是否还匹配**。
|
||||
|
||||
### 1. 状态对照表
|
||||
|
||||
| 老值(user-service 时代) | 新值(order-v2 时代) | 含义 | 前端处理建议 |
|
||||
|---|---|---|---|
|
||||
| `PENDING` | `PENDING_MODERATION` | 机审中(评价刚提交,异步跑阿里云绿网) | 若前端用此常量过滤"待审核",注意改名;建议改为判断 `status != 'APPROVED' && status != 'REJECTED'` |
|
||||
| `MACHINE_PENDING` | `PENDING_MODERATION` | 同上(并入) | 老取值建议 fallback 兼容 |
|
||||
| `MACHINE_BLOCKED` | `MACHINE_REJECTED` | 机审命中 block 级关键词,系统拒(但管理员可覆盖) | 改名 |
|
||||
| `MACHINE_REVIEW` / 其他"待人工" | `PENDING_MANUAL` | 机审命中 review 级关键词,转人工复审 | 改名 |
|
||||
| `APPROVED` | `APPROVED` | 审核通过 / 前台可见 | ✅ 不变 |
|
||||
| `REJECTED` | `REJECTED` | 人工拒绝 / 前台不可见 | ✅ 不变 |
|
||||
| `OVERRIDE_APPROVED` | 不再作为独立状态,覆盖后直接是 `APPROVED` | 原"管理员覆盖通过"独立状态 | ⚠️ 若前端用此判断"是否覆盖",改用 `machineResult.override == true` 或事件日志字段判断 |
|
||||
|
||||
### 2. 新状态机(order-v2 侧实现)
|
||||
|
||||
**5 个状态**(`ReviewStatus` 枚举):
|
||||
|
||||
| 值 | 描述 |
|
||||
|---|---|
|
||||
| `PENDING_MODERATION` | 机审中(初始状态) |
|
||||
| `PENDING_MANUAL` | 机审命中 review 级关键词,待人工复审 |
|
||||
| `MACHINE_REJECTED` | 机审命中 block 级关键词,系统拒绝 |
|
||||
| `APPROVED` | 审核通过(前台可见) |
|
||||
| `REJECTED` | 人工拒绝(前台不可见) |
|
||||
|
||||
**6 个事件**(`ReviewEvent`):
|
||||
|
||||
| 事件 | 触发 | 转移 |
|
||||
|---|---|---|
|
||||
| `MACHINE_PASS` | 阿里云绿网回调通过 | `PENDING_MODERATION` → `APPROVED` |
|
||||
| `MACHINE_FAIL_REVIEW` | 命中 review 级关键词 | `PENDING_MODERATION` → `PENDING_MANUAL` |
|
||||
| `MACHINE_FAIL_BLOCK` | 命中 block 级关键词 | `PENDING_MODERATION` → `MACHINE_REJECTED` |
|
||||
| `MANUAL_APPROVE` | 管理端 `/admin/review/{id}/approve` | `PENDING_MANUAL` → `APPROVED` |
|
||||
| `MANUAL_REJECT` | 管理端 `/admin/review/{id}/reject` | `PENDING_MANUAL` → `REJECTED` |
|
||||
| `ADMIN_OVERRIDE_APPROVE` | 管理端 `/admin/review/{id}/override-approve` | `MACHINE_REJECTED` → `APPROVED` |
|
||||
|
||||
### 3. 状态显示建议(供 hl-ui / hl-mp 参考)
|
||||
|
||||
```javascript
|
||||
// 管理端列表筛选建议
|
||||
const ADMIN_FILTER = {
|
||||
待审核: ['PENDING_MODERATION', 'PENDING_MANUAL'], // 需要管理员关注
|
||||
机审拒绝: ['MACHINE_REJECTED'], // 可覆盖通过
|
||||
已通过: ['APPROVED'],
|
||||
已拒绝: ['REJECTED'],
|
||||
};
|
||||
|
||||
// 小程序端(只关心是否已审核通过)
|
||||
if (review.status === 'APPROVED') {
|
||||
// 正常展示
|
||||
} else {
|
||||
// 一般不展示或隐藏
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、前端无感但内部链路变化
|
||||
|
||||
### 1. 创建评价:订单"已评价"标记改为强一致
|
||||
|
||||
- **老链路**(最终一致):`createReview` 成功 → afterCommit 调 `user-service.OrderReviewFeignClient → hl-order-service.PUT /internal/mp/order/{id}/mark-reviewed`(Feign 跨服务一次)
|
||||
- **新链路**(强一致):review 与 order 同库同事务,`createReview` 同事务内直接更新 `orders.is_reviewed = 1`
|
||||
- **前端体感**:
|
||||
- 创建评价响应时间预计快 **50~100ms**(省一跳 Feign)
|
||||
- 创建成功立刻查订单 `/mp/order/{orderId}` 的 `isReviewed` 字段就是 `true`,**不再有短暂不一致窗口**(老版本偶发 50ms 内查到 false)
|
||||
|
||||
### 2. 管理端审核(approve / reject / override-approve)
|
||||
|
||||
- 老:user-service 本地写 review.status → Feign 调 order-v2 → order.is_reviewed 更新
|
||||
- 新:order-v2 本地写 review.status + orders.is_reviewed(同事务)
|
||||
- 响应时间预计 **快 30~50ms**
|
||||
|
||||
### 3. 精选评价缓存键(Redis 内部实现,前端无直接感知)
|
||||
|
||||
- 前缀保持 `review:featured:limit:{limit}`,TTL 600s±60s
|
||||
- MP 侧兼容层前缀 `mp:review:featured*` 保持不变
|
||||
- 迁移后首次访问缓存 miss 约 1~3 秒回源,后续正常(业务调用量低,不影响体验)
|
||||
|
||||
---
|
||||
|
||||
## 五、响应字段清单(仅列前端需要关注的 VO)
|
||||
|
||||
### 管理端 `ReviewVO` / `ReviewListVO`(`/admin/review/**` 返回)
|
||||
|
||||
| 字段 | 类型 | 说明 | 变化 |
|
||||
|---|---|---|---|
|
||||
| `reviewId` | Long | 评价 ID | - |
|
||||
| `orderId` / `orderNo` | Long / String | 订单 | - |
|
||||
| `userId` / `userName` / `userAvatar` | Long / String | 用户 | - |
|
||||
| `productId` / `productName` / `productType` | Long / String | 产品 | productType 新增 `CUSTOM` 取值(已在 PR #935 生效,本 PR 无变化) |
|
||||
| `targetType` / `targetId` | String / Long | 评价目标(PRODUCT/CUSTOMIZER/SCENIC 等) | - |
|
||||
| `ratingItinerary` / `ratingAccommodation` / `ratingDriver` / `ratingDining` / `ratingOverall` | Integer (1~5) | 五维评分 | - |
|
||||
| `ratingLevel` | String (GOOD/MEDIUM/BAD) | 评分等级 | - |
|
||||
| `ratingAvg` | Decimal(2,1) | 平均分 | - |
|
||||
| `content` | String | 评价内容 | - |
|
||||
| `images[]` / `videos[]` | List | 图片/视频 | 字段名不变 |
|
||||
| `specialAnswers` / `keywordTags` | JSON | 特殊问题 / 关键词标签 | - |
|
||||
| `status` | String | ⚠️ 取值改,见第三节 | **改** |
|
||||
| `rejectReason` | String | 拒绝原因 | - |
|
||||
| `auditorName` / `auditedAt` | String / DateTime | 审核员/审核时间 | - |
|
||||
| `adminReplyContent` / `adminReplyBy` / `adminReplyAt` | - | 管理员回复 | - |
|
||||
| `likeCount` | Integer | 点赞数 | - |
|
||||
| `createdAt` | DateTime | 创建时间 | ✅ **保持驼峰 `createdAt`**(虽然 DB 底层列改为 `create_time` 对齐 BaseDO,但 VO 对前端零变化) |
|
||||
| `updatedAt` | DateTime | 更新时间 | ✅ 同上 |
|
||||
|
||||
### 小程序端 `MpReviewVO`(`/mp/review/**` 返回)
|
||||
|
||||
字段与 `ReviewVO` 核心一致,含 `reviewId / userName / userAvatar / productName / content / ratings* / images / videos / likeCount / createdAt / liked`(当前用户是否点赞)。
|
||||
|
||||
### `ReviewStatsVO`(统计接口返回)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `totalCount` | Long | 总评价数 |
|
||||
| `avgRating` | Decimal(2,1) | 平均评分 |
|
||||
| `goodCount` / `mediumCount` / `badCount` | Long | 好/中/差评数 |
|
||||
| `goodRate` | Decimal(5,2) | 好评率(百分比) |
|
||||
| `hasImageCount` / `hasVideoCount` | Long | 有图/有视频评价数 |
|
||||
|
||||
---
|
||||
|
||||
## 六、错误码对照
|
||||
|
||||
| HTTP | code | 说明 | 触发 |
|
||||
|---|---|---|---|
|
||||
| 200 | 200 | 成功 | - |
|
||||
| 200 | 400 | 参数错误 | 评分不在 1-5 / 必填漏传 |
|
||||
| 200 | 401 | 未登录 | `/mp/review/create` 等需 userId 的接口 |
|
||||
| 200 | 403 | 无权限 | 管理端非管理员访问 `/admin/review/**` |
|
||||
| 200 | 404 | 评价不存在 | review 已被软删或 ID 错误 |
|
||||
| 200 | 409 | 状态非法转移 | ⚠️ **新增**:cola 状态机拒绝非法流转(例:对 `APPROVED` 再 `reject`) |
|
||||
| 200 | 500 | 系统错误 | 保底 |
|
||||
| 200 | 50001 | 机审服务暂不可用 | 阿里云绿网 SDK 超时/限流 |
|
||||
|
||||
> 本项目 HTTP status 始终返回 200,业务码在 `Result.code`。
|
||||
|
||||
---
|
||||
|
||||
## 七、前端 TODO(如有硬编码)
|
||||
|
||||
- [ ] **hl-ui 管理端**:搜索项目里硬编码的评价状态字符串(例如 `status === 'PENDING'`),按第三节对照表替换
|
||||
- [ ] **hl-mp 小程序端**:
|
||||
- 大概率无需改(大部分地方直接取 `status === 'APPROVED'` 判断是否展示)
|
||||
- 如有"审核中"状态展示(例如"我的评价"列表),状态值需从 `PENDING` / `MACHINE_PENDING` 替换为 `PENDING_MODERATION` / `PENDING_MANUAL`
|
||||
- [ ] **无其它改动**:网关路径、字段命名、认证头(`X-User-Id` / `X-Admin-Id`)全部不变
|
||||
|
||||
---
|
||||
|
||||
## 八、回归验证建议(前端自测)
|
||||
|
||||
- [ ] 提交评价 → 我的评价列表能看到(`status=PENDING_MODERATION` 或 `APPROVED`)
|
||||
- [ ] 订单详情"已评价"标记立即刷新(不再有延迟窗口)
|
||||
- [ ] 产品详情/精选评价列表加载正常
|
||||
- [ ] 评价点赞/取消点赞能实时更新
|
||||
- [ ] 管理端审核通过/拒绝 → 小程序端立即可见/隐藏
|
||||
- [ ] 管理端覆盖通过(机审拒绝后)→ 评价重新可见
|
||||
|
||||
---
|
||||
|
||||
## 九、联系人
|
||||
|
||||
- 后端负责人:wx / AI 协作(管理者)
|
||||
- 相关任务文档:`docs/tasks/20260421_设计_评价模块迁移到order-v2.md`
|
||||
- 重启服务清单(后端):hl-user-service / hl-order-service-v2 / hl-mp-service / hl-product-service-v2 / hl-gateway
|
||||
正在加载...
x
在新工单中引用
屏蔽一个用户