docs(backend-fix): 测试报告 5 PR 后端修复 changelog (2026-05-07)
5 个 fix PR 合并 dev,已部署待运维同步测试服: - PR #1803 (Closes #1787) order-v2/work-order: 工单创建漏 setWorkOrderNo/setOrderNo - PR #1804 (Closes #1791) order-v2/order+refund: 列表日期范围筛选三层补字段 - PR #1805 (Closes #1789) order-v2/insurance: 投保人证件号字段名 + JsonAlias 兼容 - PR #1806 (Closes #1793) hl-user-service/explore-category: 详情 VO 缺 status - PR #1807 (Closes #1794, #1795) hl-resource-service: 景区下架引用校验 + 服务人员手机号格式 @mmg 看到请同步前端: - 工单列表/详情新增 workOrderNo + orderNo 字段 - 订单/退款列表查询参数 createTimeStart/createTimeEnd - 保险投保 idCardType/idCardNo 字段名(V1 契约,@JsonAlias 兼容) - 探索分类详情 status 字段(去掉 ?? 1 默认值) - 景区下架 errorCode SCENIC_DISABLE_IN_USE 含产品名 需重启服务:hl-order-service-v2、hl-user-service、hl-resource-service
这个提交包含在:
父节点
2b0b64248a
当前提交
c00f608a92
@ -0,0 +1,102 @@
|
||||
---
|
||||
date: 2026-05-07
|
||||
type: backend-fix
|
||||
module: hl-order-service-v2/insurance
|
||||
priority: high
|
||||
notify: ["@mmg"]
|
||||
status: deployed-pending
|
||||
restart_service: hl-order-service-v2
|
||||
gitea_pr: 1805
|
||||
gitea_issue: 1789
|
||||
related_cases: [BD-001]
|
||||
breaking_change: false
|
||||
---
|
||||
|
||||
# 投保人证件号字段名改回 V1 契约 + JsonAlias 兼容(保险订单创建修复)
|
||||
|
||||
## 现象(BD-001)
|
||||
|
||||
```
|
||||
POST /admin/insurance/purchase
|
||||
Body: {"insuredList":[{"name":"张三","idType":"ID_CARD","idNo":"110101...",...}],...}
|
||||
响应: {"code":400,"message":"证件类型不能为空, 证件号码不能为空"}
|
||||
```
|
||||
|
||||
即使前端填了证件号也报必填。
|
||||
|
||||
## 根因
|
||||
|
||||
V2 重写时单方面把 `PurchaseInsuranceRequest` 的 `idCardType / idCardNo` 改名成 `idType / idNo`。前端按 V1 契约持续传 `idCardType / idCardNo`,Jackson `FAIL_ON_UNKNOWN_PROPERTIES=false` 静默丢字段,双 @NotNull 触发必填。
|
||||
|
||||
## 修复
|
||||
|
||||
PR #1805 已合并 dev。
|
||||
|
||||
1. **DTO 改回 V1 字段名**:`PurchaseInsuranceRequest.idType → idCardType`,`idNo → idCardNo`
|
||||
2. **加 @JsonAlias 双向兼容**:`@JsonAlias({"idType"})` / `@JsonAlias({"idNo"})` —— 两种字段名都能反序列化
|
||||
3. service 层 7 处 getter/setter 引用全部跟改(含 PR #1800 拆出的 InsurancePurchaseTxService)
|
||||
|
||||
## 前端调用(@mmg)
|
||||
|
||||
### 推荐写法(两种都可,建议用 V1 字段名)
|
||||
|
||||
```js
|
||||
// ✅ 推荐:V1 契约字段名
|
||||
POST /admin/insurance/purchase
|
||||
{
|
||||
"schemeId": "2046840448906940417",
|
||||
"orderId": "...",
|
||||
"insuredList": [
|
||||
{
|
||||
"name": "张三",
|
||||
"idCardType": "ID_CARD",
|
||||
"idCardNo": "110101199001011234",
|
||||
"phone": "13800138000",
|
||||
"birthday": "1990-01-01",
|
||||
"relationship": "SELF"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// ⚠️ 兼容(@JsonAlias 兜底,但建议改用上面的)
|
||||
{
|
||||
"insuredList": [
|
||||
{"idType": "ID_CARD", "idNo": "...", ...}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 重要:同时传新旧字段时的优先级
|
||||
|
||||
如果前端代码同时传了 `idCardType` 和 `idType`(不推荐),Jackson 用最后出现的覆盖。建议**只传一种**,统一改用 V1 字段名 `idCardType / idCardNo` 跟项目其他 traveler DTO 对齐。
|
||||
|
||||
### idCardType 枚举值
|
||||
|
||||
```
|
||||
ID_CARD 身份证
|
||||
PASSPORT 护照
|
||||
HONG_KONG 港澳通行证
|
||||
TAIWAN 台湾通行证
|
||||
OTHER 其他
|
||||
```
|
||||
|
||||
### 字段加密提醒
|
||||
|
||||
`InsuredPerson.idCardNo` 已挂 `EncryptTypeHandler`,落库自动加密、查询自动解密,前端无感。日志全部已脱敏(grep 31 处零打印明文)。
|
||||
|
||||
## 重启服务
|
||||
|
||||
`hl-order-service-v2` 部署测试服后即可。
|
||||
|
||||
## 验收
|
||||
|
||||
- [ ] 用 `idCardType / idCardNo` 字段名 POST → 返 code:200 创建保险订单
|
||||
- [ ] 用 `idType / idNo`(旧字段名兜底)POST → 同样 code:200(@JsonAlias 兼容)
|
||||
- [ ] 缺失证件号 → 返必填提示
|
||||
- [ ] DB 中 idCardNo 是加密格式(解密查 InsuredPersonVO 是明文)
|
||||
|
||||
## 关联工单
|
||||
Gitea #1789 已 Closes 关闭。
|
||||
|
||||
## 备注
|
||||
本次修复保留 V2 内部其他字段(V2 重写期间引入的合理改动),仅恢复**对外契约字段名**。前端零改动也能调通(@JsonAlias 兜底),但建议主动改回 V1 字段名以保持代码清晰。
|
||||
@ -0,0 +1,183 @@
|
||||
# 订单出行人证件验证: admin 端补接口 + 前端必须改 URL/method/参数
|
||||
|
||||
> **服务**: hl-order-service-v2 (端口 8084)
|
||||
> **PR**: #1798 (已合并 dev, 待部署 prod)
|
||||
> **Issue**: #1797
|
||||
> **日期**: 2026-05-07
|
||||
> **影响范围**: 管理后台 出行人证件验证弹窗(蒋雨莲所在订单页)
|
||||
> **@ 前端**: mmg
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 关键变化(必须改前端)
|
||||
|
||||
prod 弹窗 "证件验证未通过 · 蒋雨莲:接口不存在: POST /admin/auth/cert/validate" 是因为 **`POST /admin/auth/cert/validate` 后端从未实现过**(五重证据:代码 0 命中 / git 全历史 0 命中 / changelog 0 命中 / 需求文档 0 命中 / AuthController 全部 13 个 mapping 无 cert)。
|
||||
|
||||
后端**新增**正确接口:
|
||||
|
||||
```
|
||||
GET /admin/order/{orderId}/travelers/validate
|
||||
```
|
||||
|
||||
前端必须把"逐个 traveler 调 cert/validate"的循环逻辑**整段删掉**,改为按 orderId 一次性校验:URL 变 / method 由 POST 改 GET / 参数由 traveler body 改 path orderId。
|
||||
|
||||
---
|
||||
|
||||
## 一、背景
|
||||
|
||||
弹窗触发动作(疑似锁单/支付/确认行程前置校验)应该一次性把订单内全部出行人验证一次,而不是循环逐人。后端早就有 `GET /internal/order/traveler/validate/{orderId}` 给 payment-service Feign 调,本次只是在 admin 端薄包装一层让前端可以直调。
|
||||
|
||||
---
|
||||
|
||||
## 二、变更接口清单
|
||||
|
||||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||||
|---|------|------|------|----------|------|
|
||||
| 1 | 校验订单出行人证件信息 | GET | `/admin/order/{orderId}/travelers/validate` | **新增** | 替换前端误调的 `POST /admin/auth/cert/validate` |
|
||||
|
||||
---
|
||||
|
||||
## 三、接口详情
|
||||
|
||||
### 1. 校验订单出行人证件信息 `GET /admin/order/{orderId}/travelers/validate`
|
||||
|
||||
**Service**: 复用已有 `OrderTravelerService.validateAndReturnVO(orderId)`(与 internal 接口完全对齐)
|
||||
**VO**: `TravelerValidationVO`
|
||||
|
||||
#### 入参
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| orderId | Path | Long | ✅ | 雪花 ID | 订单 ID |
|
||||
|
||||
#### 出参 `Result<TravelerValidationVO>`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| valid | Boolean | 全部出行人证件信息是否合规 |
|
||||
| travelerCount | Integer | 出行人数量 |
|
||||
| errors | `List<String>` | 校验失败明细(中文消息),合规时为空数组 |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```
|
||||
GET /admin/order/123456789/travelers/validate
|
||||
Authorization: Bearer <admin_token>
|
||||
```
|
||||
|
||||
#### 响应示例(合规)
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"valid": true,
|
||||
"travelerCount": 2,
|
||||
"errors": []
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 响应示例(不合规)
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"valid": false,
|
||||
"travelerCount": 2,
|
||||
"errors": [
|
||||
"蒋雨莲:身份证号格式错误",
|
||||
"张三:护照有效期已过"
|
||||
]
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、契约约束与正确调用方式
|
||||
|
||||
### ✅ 正确 / ❌ 错误 调用对照
|
||||
|
||||
| 场景 | 调用 |
|
||||
|------|------|
|
||||
| ✅ 一次性按订单校验全部出行人 | `GET /admin/order/{orderId}/travelers/validate` |
|
||||
| ❌ 循环逐人调 cert/validate | `POST /admin/auth/cert/validate` × N(接口不存在 404) |
|
||||
|
||||
### 前端代码改动指引
|
||||
|
||||
**旧代码(删除)**:
|
||||
```js
|
||||
for (const t of travelers) {
|
||||
await http.post('/admin/auth/cert/validate', t) // ❌ 接口不存在
|
||||
}
|
||||
```
|
||||
|
||||
**新代码**:
|
||||
```js
|
||||
const { data } = await http.get(`/admin/order/${orderId}/travelers/validate`)
|
||||
if (!data.valid) {
|
||||
// 弹窗显示 data.errors 即可
|
||||
showCertValidationDialog(data.errors)
|
||||
}
|
||||
```
|
||||
|
||||
错误明细 `errors: List<String>` 已经包含中文姓名 + 错误原因,前端不需要再拼姓名前缀。
|
||||
|
||||
---
|
||||
|
||||
## 五、数据库行为
|
||||
|
||||
只读校验,**不写库**。
|
||||
|
||||
---
|
||||
|
||||
## 六、边界行为
|
||||
|
||||
- orderId 不存在 → 服务端 BusinessException → `Result.code != 200` + 中文 message
|
||||
- 订单存在但 0 个出行人 → `valid=false, travelerCount=0, errors=["订单尚未添加出行人"]`
|
||||
- 未登录 → 网关 401 拦截
|
||||
- 下游服务降级 → 暂不需要 fallback,service 内部不依赖外部服务
|
||||
|
||||
---
|
||||
|
||||
## 七、不影响范围
|
||||
|
||||
- **仅影响**: 管理后台出行人证件验证弹窗(前端 hl-ui mmg 维护)
|
||||
- **零影响**:
|
||||
- 小程序端出行人列表 / 添加 / 编辑
|
||||
- admin 端出行人增删改 (`/admin/order/{orderId}/travelers/**`)
|
||||
- payment-service 内部 Feign 调用的 `/internal/order/traveler/validate/{orderId}` 保持不变
|
||||
- 历史数据零变更
|
||||
|
||||
---
|
||||
|
||||
## 八、测试环境已验证
|
||||
|
||||
后端单测 3 用例全绿(mockMvc 真路径 dispatch):
|
||||
- `validate_orderComplete_returnsSuccessVO` ✓
|
||||
- `validate_orderIncomplete_returnsIncompleteVO` ✓
|
||||
- `validate_invalidOrderId_serviceThrows_exposedAsBusinessError` ✓
|
||||
|
||||
测试服 admin token round-trip:待 PR #1798 部署到测试服后 /@qa 角色验证(24h 内回贴 curl 输出)。
|
||||
|
||||
---
|
||||
|
||||
## 九、相关历史 PR
|
||||
|
||||
| PR | Issue | 说明 | 是否仍有效 |
|
||||
|----|-------|------|------------|
|
||||
| 无 | 无 | 后端从未约定 `POST /admin/auth/cert/validate` 接口 | -- |
|
||||
| **本 PR #1798** | **#1797** | 新增 `GET /admin/order/{orderId}/travelers/validate` | ✅ 最新 |
|
||||
|
||||
---
|
||||
|
||||
## 十、相关文档
|
||||
|
||||
- 关联 Issue: [wx/HL#1797](https://git.1814.love:8443/wx/HL/issues/1797)
|
||||
- 关联 PR: [wx/HL#1798](https://git.1814.love:8443/wx/HL/pulls/1798)
|
||||
@ -0,0 +1,74 @@
|
||||
---
|
||||
date: 2026-05-07
|
||||
type: backend-fix
|
||||
module: hl-order-service-v2/order+refund
|
||||
priority: high
|
||||
notify: ["@mmg"]
|
||||
status: deployed-pending
|
||||
restart_service: hl-order-service-v2
|
||||
gitea_pr: 1804
|
||||
gitea_issue: 1791
|
||||
related_cases: [DD-004, DD-005, TK-004]
|
||||
---
|
||||
|
||||
# 订单/退款列表日期范围筛选无效 — 三层补字段
|
||||
|
||||
## 现象(DD-004 / DD-005 / TK-004)
|
||||
|
||||
测试报告:
|
||||
- 订单列表选起止日期 → 无法筛选
|
||||
- 订单列表多条件组合 → "日期还是有问题"
|
||||
- 退款列表多条件组合 → "无"
|
||||
|
||||
`/@bug` round-trip 极端测试 1900 vs 2099 vs 默认三组 total 都 29 一致 → 日期参数被静默丢弃。
|
||||
|
||||
## 修复
|
||||
|
||||
PR #1804 已合并 dev。三层补字段:
|
||||
|
||||
| 层 | 文件 | 改动 |
|
||||
|----|------|------|
|
||||
| VO | OrderPageReqVO + RefundApplicationPageReqVO | 加 `createTimeStart` / `createTimeEnd` (LocalDateTime + @DateTimeFormat) |
|
||||
| Service | OrderListQueryService.listAdminOrders | 透传两个新参数到 mapper |
|
||||
| Mapper | OrderInfoMapper.selectAdminPage / RefundApplicationMapper.selectPage | wrapper 加 `betweenIfPresent(OrderInfo::getCreateTime, start, end)` |
|
||||
|
||||
`betweenIfPresent` 智能退化:双边都给 = BETWEEN,只给 start = >= start,只给 end = <= end,都空跳过。
|
||||
|
||||
## 前端调用(@mmg)
|
||||
|
||||
### 订单列表
|
||||
|
||||
```js
|
||||
// 接口:GET /admin/order/page
|
||||
GET /admin/order/page?createTimeStart=2026-04-01T00:00:00&createTimeEnd=2026-04-30T23:59:59&page=1&pageSize=10
|
||||
```
|
||||
|
||||
注意:
|
||||
- 字段名:`createTimeStart` / `createTimeEnd`(驼峰,跟之前 status 字段一致)
|
||||
- 格式:ISO 8601 DateTime(`2026-04-01T00:00:00`)
|
||||
- 时区:服务端 `+08:00`,前端传字符串不带时区由后端 LocalDateTime 解析
|
||||
|
||||
### 退款列表
|
||||
|
||||
```js
|
||||
// 接口:GET /admin/refund/application/page
|
||||
GET /admin/refund/application/page?createTimeStart=...&createTimeEnd=...&page=1&pageSize=10
|
||||
```
|
||||
|
||||
### 不传日期时
|
||||
|
||||
向后兼容,不传 `createTimeStart` / `createTimeEnd` 行为完全不变(既有调用零影响)。
|
||||
|
||||
## 重启服务
|
||||
|
||||
`hl-order-service-v2` 部署测试服后即可。
|
||||
|
||||
## 验收
|
||||
|
||||
- [ ] 订单列表传日期 → 数据按范围筛选
|
||||
- [ ] 退款列表传日期 → 同样工作
|
||||
- [ ] 不传日期 → 全量返回(向后兼容)
|
||||
- [ ] 跨年 / 单边 / 边界 各 case 正常
|
||||
|
||||
## 关联工单
|
||||
Gitea #1791 已 Closes 关闭。
|
||||
@ -0,0 +1,69 @@
|
||||
---
|
||||
date: 2026-05-07
|
||||
type: backend-fix
|
||||
module: hl-order-service-v2/work-order
|
||||
priority: high
|
||||
notify: ["@mmg"]
|
||||
status: deployed-pending
|
||||
restart_service: hl-order-service-v2
|
||||
gitea_pr: 1803
|
||||
gitea_issue: 1787
|
||||
related_cases: [GD-001]
|
||||
---
|
||||
|
||||
# 工单新增漏 setWorkOrderNo / setOrderNo + 清理 title 死字段
|
||||
|
||||
## 现象(GD-001)
|
||||
|
||||
```
|
||||
POST /admin/order/work-order
|
||||
Body: {"orderId":1,"type":"OTHER","description":"...","priority":"NORMAL"}
|
||||
响应: {"code":400,"message":"字段【work_order_no】未填写,请填写后重试"}
|
||||
```
|
||||
|
||||
## 修复
|
||||
|
||||
PR #1803 已合并 dev。改动:
|
||||
|
||||
1. `WorkOrderService.create()` 新增 `generateWorkOrderNo()` 私有方法,格式 `WO + yyyyMMddHHmmss + 4位随机`(20 字符),落库前 set 到 entity
|
||||
2. 同时 `setOrderNo(order.getOrderNo())` 拷贝订单号
|
||||
3. 删除 `CreateWorkOrderRequest.title` 死字段(DDL/entity 没列)
|
||||
4. 删除 `WorkOrderVO.title` 死字段,新增 `workOrderNo` 字段(响应里返工单号给前端)
|
||||
5. `sql/work_order.sql` `type` COMMENT 对齐枚举(`CHANGE/COMPLAINT/SUPPLEMENT/OTHER`)
|
||||
|
||||
## 前端配合(@mmg)
|
||||
|
||||
### 1. 请求 body 不再传 title
|
||||
|
||||
之前如果前端传了 title,会被静默吞掉(无 setter)。现在 DTO 删了 title 字段,传过来会被 Jackson 忽略(项目 FAIL_ON_UNKNOWN_PROPERTIES=false),不影响业务但建议清理。
|
||||
|
||||
### 2. 响应 body 多了 workOrderNo 字段
|
||||
|
||||
工单列表/详情响应现在包含:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "2052278173260824577",
|
||||
"workOrderNo": "WO20260507150123ABCD", // ← 新增字段
|
||||
"orderNo": "HL26050700001", // ← 新增字段
|
||||
"orderId": "...",
|
||||
"type": "OTHER",
|
||||
"status": "PENDING",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
前端工单列表/详情页可以展示这两个字段。
|
||||
|
||||
## 重启服务
|
||||
|
||||
`hl-order-service-v2` 已合并到 dev,运维部署测试服后即可使用。如本地启动需重启 `hl-order-service-v2`。
|
||||
|
||||
## 验收
|
||||
|
||||
- [ ] 测试服部署后 admin token POST 工单 → 返 code:200 + workOrderNo + orderNo
|
||||
- [ ] 前端工单列表展示工单号
|
||||
- [ ] 工单详情展示工单号 + 订单号
|
||||
|
||||
## 关联工单
|
||||
Gitea #1787 已 Closes 关闭。
|
||||
@ -0,0 +1,85 @@
|
||||
---
|
||||
date: 2026-05-07
|
||||
type: backend-fix
|
||||
module: hl-resource-service/scenic+staff
|
||||
priority: low
|
||||
notify: ["@mmg"]
|
||||
status: deployed-pending
|
||||
restart_service: hl-resource-service
|
||||
gitea_pr: 1807
|
||||
gitea_issue: [1794, 1795]
|
||||
related_cases: [JQ-011, RY-002]
|
||||
---
|
||||
|
||||
# 景区下架引用校验 + 服务人员手机号格式校验
|
||||
|
||||
## 现象
|
||||
|
||||
- **JQ-011**:景区被产品引用时 admin 直接下架,无业务校验提示
|
||||
- **RY-002**:服务人员录入手机号格式校验缺失(`abc123` / `12345` 都能保存)
|
||||
|
||||
## 修复
|
||||
|
||||
PR #1807 已合并 dev,两个工单合一个 PR。
|
||||
|
||||
### #1794 景区下架引用校验
|
||||
|
||||
`ScenicSpotService.updateStatus` + `batchUpdateStatus` 加 `productFeignClient.checkResourceInUse("SCENIC", id)`:
|
||||
- 仅下架(STATUS_OFF)触发,上架不触发
|
||||
- 单个被引用 → 抛 `BusinessException(SCENIC_DISABLE_IN_USE, 产品名)`,message 含产品名(如"景区已被【XX 一日游】使用,请先解除关联")
|
||||
- 批量被引用 → 跳过+log.warn(与既有 approvalNo 跳过模式一致)
|
||||
|
||||
### #1795 服务人员手机号校验
|
||||
|
||||
`StaffCreateRequest.phone` + `emergencyPhone` 加 `@Pattern(regexp = "^$|^1[3-9]\\d{9}$", message = "手机号格式不正确")`,`StaffUpdateRequest` 同样。
|
||||
|
||||
允许空字符串(phone 是非必填字段),非空必须符合 11 位手机号格式。
|
||||
|
||||
## 前端配合(@mmg)
|
||||
|
||||
### 景区下架弹窗
|
||||
|
||||
下架接口现在可能返 errorCode `SCENIC_DISABLE_IN_USE`,前端可以 catch 这个错误码,弹窗提示用户解除关联:
|
||||
|
||||
```js
|
||||
try {
|
||||
await offlineScenic(id)
|
||||
} catch (e) {
|
||||
if (e.code === xxxxx /* SCENIC_DISABLE_IN_USE 错误码 */) {
|
||||
showDialog({
|
||||
title: '景区已被使用',
|
||||
content: e.message, // 含产品名
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 服务人员手机号
|
||||
|
||||
前端可以增加同样的格式校验提供更好体验(同步反馈),但即使没加,后端会拦截并返业务码非 200。
|
||||
|
||||
## 重启服务
|
||||
|
||||
`hl-resource-service` 部署测试服后即可。
|
||||
|
||||
## 验收
|
||||
|
||||
- [ ] 关联中景区下架 → 业务码非 200 + 含产品名提示
|
||||
- [ ] 无关联景区下架 → 正常下架
|
||||
- [ ] 服务人员手机号 "abc" → 业务码非 200
|
||||
- [ ] 手机号 "13800138000" → 正常保存
|
||||
- [ ] emergencyPhone 同样校验
|
||||
|
||||
## 关联工单
|
||||
- Gitea #1794 已 Closes 关闭
|
||||
- Gitea #1795 已 Closes 关闭
|
||||
|
||||
## 备注:项目级遗留(建议另立工单跟踪,不在本 PR 范围)
|
||||
|
||||
/@bug 顺手发现两个项目级问题,**不在本 PR 修复范围**:
|
||||
|
||||
1. **8 个资源服务(hotel/scenic/activity/restaurant/staff/supplies/cost/vehicle)的 `updateStatus` 方法全部缺 `checkResourceInUse`**,本 PR 只修景区一个。其余 7 个建议 PM 决策是否扩大修复范围。
|
||||
2. **hl-resource-service 整体无字段加密**:`Staff.phone / emergencyPhone / 身份证号` 等敏感字段未挂 `EncryptTypeHandler`(grep `EncryptTypeHandler` 整模块零匹配)。
|
||||
3. **`ProductFeignFallbackFactory.checkResourceInUse` 降级返回空 list = fail-open**:product-service 真挂时景区会被偷偷下架。
|
||||
|
||||
以上 3 项建议 PM 评估优先级后另立 feat/refactor 工单。
|
||||
@ -0,0 +1,84 @@
|
||||
---
|
||||
date: 2026-05-07
|
||||
type: backend-fix
|
||||
module: hl-user-service/explore-category
|
||||
priority: medium
|
||||
notify: ["@mmg"]
|
||||
status: deployed-pending
|
||||
restart_service: hl-user-service
|
||||
gitea_pr: 1806
|
||||
gitea_issue: 1793
|
||||
related_cases: [ZT-006]
|
||||
---
|
||||
|
||||
# 探索分类详情接口补 status 字段(前端称"主题列表"状态切换无效)
|
||||
|
||||
## 现象(ZT-006)
|
||||
|
||||
测试报告:admin 端切换探索分类(前端口语称"主题")的上下架状态,**显示"编辑成功"但实际状态没变**。
|
||||
|
||||
## 根因
|
||||
|
||||
`ExploreCategoryDetailVO.java` **完全缺 `status` 字段**,导致 `ExploreCategoryService.toDetailVO` builder 也不 set status,前端 EditModal `status: data.status ?? 1` fallback 默认上线,用户切换的真实状态无法回显。
|
||||
|
||||
## 修复
|
||||
|
||||
PR #1806 已合并 dev。
|
||||
|
||||
1. `ExploreCategoryDetailVO` 加 `private Integer status;` 字段,@ApiModelProperty 含字典值说明
|
||||
2. `ExploreCategoryService.toDetailVO` builder 加 `.status(category.getStatus())` 一行
|
||||
|
||||
PUT 切换接口本身是正常的,问题只在 GET detail 不返 status。
|
||||
|
||||
## 前端配合(@mmg)
|
||||
|
||||
### 1. 详情响应多了 status 字段
|
||||
|
||||
```json
|
||||
GET /admin/explore/category/{id}
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"id": "...",
|
||||
"name": "亲子游",
|
||||
"iconUrl": "...",
|
||||
"status": 1, // ← 新增字段(0=下架, 1=上架)
|
||||
"sortOrder": 100,
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 前端建议改默认值
|
||||
|
||||
```js
|
||||
// 错误(导致"切换无效"幻觉)
|
||||
status: data.status ?? 1 // ❌ 后端返 null 时默认 1
|
||||
|
||||
// 正确(后端现在永远返字段,可以去掉 fallback)
|
||||
status: data.status // ✅ 直接用后端字段
|
||||
// 或
|
||||
status: data.status ?? 0 // ✅ 兜底用 0(下架)更安全
|
||||
```
|
||||
|
||||
## 重启服务
|
||||
|
||||
`hl-user-service` 部署测试服后即可。
|
||||
|
||||
## 验收
|
||||
|
||||
- [ ] admin GET 探索分类详情 → 响应含 status 字段非 null
|
||||
- [ ] 切换 status 后再次 GET → status 已变
|
||||
- [ ] 下架的分类 detail 返 0 不是 1
|
||||
- [ ] 前端编辑弹窗状态开关正确回显
|
||||
|
||||
## 数据修复(建议运营/QA 配合)
|
||||
|
||||
BUG 期间用户切换状态可能有错位,运营可参考 BUG 报告里的审计 SQL 对照修:
|
||||
`docs/tasks/20260507_bug_product_analysis.md`(仓库内)。
|
||||
|
||||
## 关联工单
|
||||
Gitea #1793 已 Closes 关闭。
|
||||
|
||||
## 顺手提醒(CP-006 不在本 PR)
|
||||
测试报告里 CP-006 "产品筛选下拉框只有上/下架,适用小蒙马" 是**不同根因**(产品筛选选项不全),归到产品复核任务,不在本 PR 范围。
|
||||
正在加载...
x
在新工单中引用
屏蔽一个用户