3.4 KiB
修复:资源(酒店/景点/活动等)启用禁用审批提交全部失败
类型: 后端 BUG 修复 关联: 工单 #1550 / PR #1551 日期: 2026-04-30 影响范围: 管理后台资源(酒店/景点/活动/餐厅/车辆/服务/备品/员工/成本/房型) 申请上架/下架审批
现象
管理后台 web.test.1814.love:9443/hotel/list 等所有资源管理页点击「申请上架/申请下架」全部报:
提交审批失败: Failed to submit approval to enterprise WeChat
后端日志(企微返回):
ERROR WechatApiClient - WeChat oa/applyevent error: errcode=301025, errmsg=get approval param error:Text-1771171809841
近 30 天 user-service 日志中没有任何一条 "Approval submitted" 成功记录 — 也就是说资源审批从未成功过。
根因(双层)
第 1 层:reason 含换行符
10 个 resource service(Hotel/RoomType/Scenic/Activity/Restaurant/Vehicle/ServiceItem/Staff/Supplies/CostItem)拼接审批理由时统一用了:
dto.setReason((reason != null ? reason + "\n" : "") + "查看详情: " + dto.getDetailUrl());
但企微 OA 模板 C4ehNuudNWL8zXJBoApGCUEgu8knjyprtkKiRLkET 的 reason 控件 Text-1771171809841 经 gettemplatedetail 接口验证实际是 Text(单行),不允许换行符 \n。
第 2 层:setReason 顺序在 setDetailUrl 之前
10 个 service 中有 8 个的代码顺序:
dto.setReason(... + "查看详情: " + dto.getDetailUrl()); // ← 此时 detailUrl 还是 null
dto.setDetailUrl(...);
reason 末尾拼接的 dto.getDetailUrl() 调用时 detailUrl 还没 set,实际拼出的是:
<用户输入>\n查看详情: null
修复内容
1. InternalApprovalController.java:441 保持 buildTextControl
(本次同时 revert 了昨日 PR #1549 的错误改动 buildTextareaControl,因为企微模板真实定义就是 Text 单行)
2. 10 个 resource service 拼接 reason 改为空格
dto.setDetailUrl(detailUrlPrefix != null && !detailUrlPrefix.isEmpty()
? detailUrlPrefix + xxxId : "");
dto.setReason((reason != null ? reason + " " : "") + "查看详情: " + dto.getDetailUrl());
变更点:
\n→ 空格(避免 Text 单行控件不收换行符)setDetailUrl提前到setReason之前(保证 reason 末尾拼到的 detailUrl 不是 null)
3. 单测覆盖
InternalApprovalControllerTest.submitApproval_resourceReason_useTextControl:用 ArgumentCaptor 抓 controls 列表,断言资源审批的 reason 控件 control == "Text" 且 value 不含 \n,防回归。
修复后行为
测试服 round-trip(用 wx 账号 enterpriseWechatId=842)4 种资源 + 申请上架,4 次全部成功提交到企微 OA:
| 资源类型 | 操作 | 结果 spNo |
|---|---|---|
| hotel | 申请上架 | 202604300001 |
| activity | 申请上架 | 202604300002 |
| restaurant | 申请上架 | 202604300003 |
| supplies | 申请上架 | 202604300004 |
后端日志全部为 INFO Approval submitted: sp_no=...,无任何 301025 错误。
前端处理
零影响。前端无须改动 — 提交审批接口签名/响应结构完全没变,前端只看 code/message/data.spNo,原本对错误的处理逻辑也无变化(成功/失败分支都对)。
部署状态
- ✅ PR #1551 合并到 dev (sha feb248c3)
- ✅ 测试服 hl-user-service 8081/8181 滚动重启
- ✅ 测试服 hl-resource-service 8082/8182 滚动重启
- ✅ Round-trip 4 种资源类型「申请上架」全部成功