出港仓库(07,module_gjc): - IntExpStorageUseActivity 手机布局:搜索行+三格统计(总票数/未清仓/已清仓, clearNormal=0/1 双 pageQueryTotal 仅手机发起)+卡片级四操作按钮(清仓/修改 库位/出库/入库,已清仓置灰),取代平板勾选+底部批量条,复用既有 performXxx 链路 - 详情/运单追踪复用出港查询已适配页(GjcQueryDetailsActivity/LogDetailActivity),零新增页面 - 清仓/入库/修改库位弹框双变体化(手机底部弹层);修改库位手机版增加「原库位」单选; 出库确认 AlertDialog → ConfirmDialogModel(项目强制规范) 进港仓库(08,module_gjj,07 的进港镜像): - IntImpStorageUseActivity 手机布局:搜索框「运单号/航班号」分流(含字母→fno, 抓包证实)+始发站字段/筛选(fdep 入参) - 进港详情 IntImpQueryDetailsActivity + 3 Fragment 首次手机适配(报文区 3 项, 件重区直取 inPc/inWeight,库位卡片优先中文姓名) - 修改库位手机弹层「原库位」只列未出库库位(沿用平板校验) 公共:GjcMaWb 增加 isCleared 计算属性;新增 bg_phone_btn_disabled;手机首页 「国际」Tab 增加出港仓库/进港仓库入口;debug manifest 直启项 验证:双端 Proxyman Map Local mock 口径验证通过(开发机不在内网),平板回归一致, 崩溃 0;后端缺口 5 项登记问题清单 #23~#27(筛选入参缺失/clearNormal 分项统计与 detail 推断字段待内网实测) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4.7 KiB
Proxyman MCP:抓包 / 直调 / Mock(阶段 2、5、6 的调试利器)
Proxyman 桌面端 + mcp__proxyman__* 工具(会话内直接可用,缺 schema 时用 ToolSearch
select:mcp__proxyman__get_flows,... 加载)。2026-07-31 已在出港查询页全链路实测:
抓包核对请求体、Map Local mock 三种卡片形态(含真实数据不存在的「未入库」兜底态)一次跑通。
与 api-doc 的分工(先契约后事实)
| api-doc MCP | Proxyman MCP | |
|---|---|---|
| 回答什么 | 契约:接口该有什么入参/出参、参数名叫什么 | 事实:App 实际发了什么、后端实际回了什么 |
| 用在何时 | 阶段 2 开工前逐接口核对 | 阶段 5/6 实机验证与 corner case 补测 |
标准配合流程:
api-doc 拿权威参数名 → 前端实现 → Proxyman flow 核对请求体确实带上了 →
compose 改参 A/B 验证后端认不认 → 不认 → 记问题清单(附 export_flow_curl 证据)→
map local 造 mock 补 UI corner case 验证。
接入(一次性,实测步骤)
# 1) 确认 Proxyman 在跑(返回 Recording: Active + 端口,默认 9090)
# mcp__proxyman__get_proxy_status
# 2) 模拟器全局代理指向宿主机(模拟器视角宿主机 = 10.0.2.2)
adb -s <serial> shell settings put global http_proxy 10.0.2.2:9090
# 3) 验证完【必须】清掉,否则 Proxyman 一关模拟器就断网,下次验证莫名全挂
adb -s <serial> shell settings put global http_proxy :0
本项目内网服务是纯 HTTP(192.168.1.250:8093)→ 不需要装证书,明文直接可见。
(若未来切 HTTPS,才需要 install_certificate + enable_ssl_proxying。)
场景 1:核对请求/响应(替代 ui_probe req)
logcat 抓 OkHttp 多行 pretty JSON 脆弱且要人肉拼接;Proxyman 一步到位:
filter_flows(key=url, value="IntExpSearch")→ 拿 flow ID 列表get_flow_detail(flow_id)→ 完整请求体 + 响应体 + headers(Authorization 自动脱敏)
出参无文档定义时(如 IntExpSearch/detail 返回裸 Map),用真实 flow 的 responseBody
直接盘点字段清单——判定「锁定状态/计费重量是否存在」这类问题的最快路径。
场景 2:直调后端 A/B 验证(替代 run-as 提 token + 手写 curl)
create_compose_http_from_flow(从真实 flow 复制请求,token 自动带上,不用碰
shared_prefs)→ update_compose_http 改一个参数 → send_compose_http 看结果对比。
isFclose 这类「参数是否生效」的 A/B 实验用这条链。给后端提缺口时用
export_flow_curl 导出可复现的 curl 附进问题清单。
场景 3:Map Local 造 mock 验证 corner case(替代代码注入样例 Bean)
老流程「Activity 临时注入 Bean → 截图 → 删码 → 重构建」彻底淘汰:零代码改动、零重构建。
create_map_local:url 精确到接口路径,method=POST,response_body 直接写目标 JSON (构造空字段/超长文本/罕见状态,比如出港查询的 fclose+opDate 双空「未入库」兜底态)- 改真实响应个别字段更省事时用
create_map_local_from_flow - 验证完
delete_rule(rule_type=maplocal)+ 清代理,规则残留会污染后续真实数据验证
响应结构照抄真实 flow 的顶层结构(如 pageQuery 是裸 PageInfo:{total, list, pages, ...},
不要包 {status, data})。
⚠️ 实测坑(2026-07-31 出港仓库):mock BaseResultBean 包装的接口(pageQueryTotal/detail 等)时,
status 必须写 "1"——BaseResultBean.verifySuccess() 判 status == "1",写 "200" 会被当失败
静默丢弃(UI 保持默认值,无任何报错,排查靠 flow 已命中但 UI 不变这一矛盾现象)。
⚠️ 实测坑:mock 响应到达后 UI 渲染可能滞后(冷启动首帧 Davey 卡顿 2s+),
截图断言前先 ui_probe texts 确认数据已上屏——这次就因截图太早误判过一轮「mock 没生效」,
其实 get_flow_detail 里 matchedTools: ["Map Local"] 早已证明规则命中,UI 只是还没画完。
场景 4:环境模拟(按需)
create_network_condition:弱网/高延迟,验证 loading 弹窗与超时提示create_breakpoint:单次拦截改包(比 map local 更临时的一次性实验)create_map_remote:把请求转发到另一环境(如后端修复验证用的测试实例)
验证收尾清单
list_rules确认无本次遗留规则(maplocal/breakpoint/network_condition)- 模拟器代理已清(
settings get global http_proxy应为:0或空) - 用真实数据再过一遍被 mock 过的页面,确认无假数据残影