Files
aerologic-app/.claude/skills/phone-adapt/references/api-doc.md
YANG JIANKUAN 49f11ef8e6 fix: 进港移库归属更正——删除误建IntImpMove,重新适配到国内进港DomImpMove
设计稿11「进港移库」经确认归属国内进港移库(DomImpMove后端8接口齐全),
此前误判为国际进港并预接了不存在的IntImpMove模块(问题清单#31作废)。

- 删除module_gjj的IntImpMove全套实现(3页面+Bean+Api+菜单+路由+权限串)
- GnjMoveStashListActivity双形态适配:待移库/已移库Tab走search/searchMoved
  双端点,Tab角标、筛选弹层4项、全选/批量移库复用平板既有链路
- 新增手机专属页:运单详情(Intent传bean零请求)+拍照上传(detail回填
  已有照片,modify最小体三字段提交,与平板移交编辑页同链路)
- 手机首页入口改挂国内Tab(GnViewModel补通用route跳转,权限串AppDomImpMove)
- 内网真实数据双端验证通过;Proxyman A/B:wbNo/awbType生效,
  fdate/fno/spCode被后端静默忽略(#32)、opId/opDate恒null(#33)
- 问题清单更正#31+新增#32~#34,CLAUDE.md/CHANGELOG/api-doc.md同步

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 12:17:10 +08:00

161 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# api-doc MCP接口定义核对流程阶段 2 必读)
适配页面前,**所有用到的接口都要在 api-docAgentFox里核对一遍入参/出参**
不要靠平板代码或猜测推断参数名——出库交接就因为猜了 `hoState`(实际是 `handoverState`
白白折腾了一轮实机排查。
## 连接方式
项目 `.mcp.json` 已配置 `api-doc` 远程 HTTP MCP。若会话内 MCP 工具可直接调用
`mcp__api-doc__*`),直接用;**若工具没有注入会话**ToolSearch 搜不到),用 curl 走
MCP 协议手工调用,三步:
```bash
URL=$(python3 -c "import json;print(json.load(open('.mcp.json'))['mcpServers']['api-doc']['url'])")
AUTH="Authorization: $(python3 -c "import json;print(json.load(open('.mcp.json'))['mcpServers']['api-doc']['headers']['Authorization'])")"
# 1) initialize从响应头 mcp-session-id 取会话 id
curl -s -D /tmp/mcp_headers.txt -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"claude-code","version":"1.0"}}}' > /dev/null
SID=$(grep -i 'mcp-session-id' /tmp/mcp_headers.txt | tr -d '\r' | awk '{print $2}')
# 2) initialized 通知(必须发,否则 tools/* 报 session 未初始化)
curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" -H "mcp-session-id: $SID" \
-d '{"jsonrpc":"2.0","method":"notifications/initialized"}' > /dev/null
# 3) tools/call响应是 SSE`sed 's/^data: //'` 后按 JSON 解析)
curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" -H "mcp-session-id: $SID" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_endpoints","arguments":{"keyword":"IntExpMove"}}}'
```
## 可用工具5 个)
| 工具 | 用途 |
|------|------|
| `get_project_overview` | 项目概览 + 模块清单(首次调用) |
| `list_modules` | 全部模块含描述 |
| `list_endpoints` | 单模块内接口列表(分页,`moduleId` + `cursor` |
| `search_endpoints` | 按关键字搜接口(`keyword` 用控制器前缀最准,如 `IntExpOutHandover` |
| `get_endpoint_detail` | **核心**单接口完整契约schema 已拍平成字段表(`endpointId` |
## 核对清单(每个页面做一遍)
对 ViewModel 里每个 `NetApply.api.xxx` 调用:
1.`module_base/.../http/net/Api.kt` 拿到 `@POST` 路径 → `search_endpoints` 找到接口 → `get_endpoint_detail`
2. **入参**:前端传的每个 key 必须能在文档字段表里找到**同名字段**;找不到 = 传了也白传(后端静默忽略,不报错)
3. **类型**:状态类字段(`moveState`/`handoverState`/`outState`)文档均为 integer前端传 `"0"` 字符串靠
Jackson 隐式转换(实测可用);新代码尽量传数字
4. **出参**:设计稿卡片/详情页的每个展示字段,都要能对上出参字段;对不上就是后端缺口
5. **结论落两处**
- 后端缺口(缺入参/缺出参/数据不回填)→ 记入 `documents/后端接口对接问题清单.xlsx`
(按「模块 → 页面 → 接口定义 → 接口地址」格式,含前端现状与期望,状态标 ⏳/🔍)
- 前端可自行解决的(参数名写错、字段绑错)→ 直接改代码,别记成后端问题
## 已核对过的语义(别再猜)
- `IntExpOutHandover`:交接状态入参 = `handoverState`(不是 `hoState`**2026-07-29 内网实测过滤生效**
(传 0/1 分别返回纯净的待/已交接集合,字符串 `"0"`/`"1"` 同样被接受);`ldId` 是**组装人**不是交接人;
交接人姓名出参 `hoUserName`,编码 `hoId`;查询入参**没有**交接人筛选(后端缺口 #4
- `IntExpOutHandover/pageQueryTotal`**出参恒 0**(任何条件下 totalPc/totalWeight/wbNumber 均为 0
与同条件 pageQuery 不一致,后端缺口 #6)——依赖它的 Tab 角标/底部统计显示 0 不是前端问题
- `IntExpMove`:出参无航班字段(缺口 #1)、无操作人姓名(缺口 #2`opId`/`opdate`/`businessType`
文档有定义但实测恒 null缺口 #3`pageQueryTotal` 正常(与 pageQuery 口径一致,`moveState` 过滤生效)
- `typeCode/getSpecialCodeByParam``flag=1` 国际,`ieFlag` 必须传空串(传 `"E"` 返回空数组)
- `eqm/uld`ULD信息6 个端点):查询入参仅 `uld`/`status`/`uldSuffix`uldSuffix 名义是
"uld后两位",实际就是**按所属航司筛选**,配 `DictUtils.getIntCarrierList``status` 仅两态
0 正常/1 故障(三态需求=缺口 #7);无「来源」字段(#8)、无 `checkInDate`/`ifNo` 筛选入参(#9)、
无批量删除(#10`deleteUld``@Query` 单条);出参 `ifNo`/`efNo`/`checkInDate`/`checkOutDate`
文档无描述,按命名推断进/出港航班号与出入库时间(#11 待确认)
- `IntExpArrive`出港运抵2026-07-30 内网实测):`declareStatus`(申报状态)只在出参,
`pageQuery`/`pageQueryTotal` 入参均无此字段(缺口 #20,待运抵/已运抵 Tab 靠客户端拆分);
`declareStatus`/`GjcHaWb.arrivalStatus` 三色编码:`01`=正常(绿)、`W`=靛蓝态、其余非空=琥珀异常态;
`haWbList[].response`/`arrivalOpDate` 是回执文本与对应时间,实测确认真实存在非空数据;
分单补充收发货人信息**后端完全没有对应接口**`search_endpoints``IntExpArrive`/`HaWb`
关键字均搜不到分单更新接口,只有国际进港的 `IntImpAirManifest/complete`
实机调用拟定路径 `IntExpArrive/haWb/supplement` 确认 404缺口 #19
- `IntExpSearch`出港查询2026-07-31 内网实测):查询入参 `outState`/`fno`/`dest`/`spCode`/`awbType`/
`businessType`/`goodsCn`/`beginDate`/`endDate`/`agentCode`/`wbNo` 全部真实生效(平板既有口径);
文档定义的 `isFclose`(筛选航班是否关闭)**pageQuery 与 pageQueryTotal 均静默忽略**A/B 对照
全量 72 票与单日两组,加参前后结果完全一致,缺口 #21`pageQueryTotal` 出参无已入库/已离港
分项计数(#21`detail` 出参 Map 无 `lockStatus`(锁定状态)与计费重量字段(#22
详情「入库件数/入库重量」= `warehouseList` 各批次 pc/weight 求和mock 与实测均吻合);
卡片状态推断口径:`fclose` 非空=已离港、否则 `opDate` 非空=已入库;
特码字典沿用 `DictUtils.getSpecialCodeList(flag=1, ieFlag="")`ieFlag 必须空串)
- `IntExpStorageUse`出港仓库2026-07-31 文档核对,内网 A/B 未测——当日开发机不在内网):
`pageQuery`/`pageQueryTotal` 同一套入参 schema`fdate`/`fno`/`wbNo`/`likeNo`/`spCode`/`dest`/
`agentCode`/`location`/`clearNormal`/`checkIn`/`reviewStatus`/`dep`/`hno`/`prefix`;设计稿筛选的
**运单类型/业务类型/品名(中) 均无入参**`awbType`/`businessType`/`goodsCn`,缺口 #23
手机三格统计按 `clearNormal=0/1` 各调一次 `pageQueryTotal``wbNumber`,该过滤**是否真实生效
待内网 A/B**(缺口 #24,参照 isFclose 有定义但被忽略的先例);出参 `clearNormal` 0=未清仓/1=已清仓
(卡片标签与「清仓」按钮置灰按 ==\"1\" 判定);详情复用 `IntExpSearch/detail`maWbId Query 参数)
- `IntImpStorage`进港仓库2026-07-31 文档核对;**注意前端 Api.kt 路径前缀是 `IntImpStorage`
不是 `IntImpStorageUse`**api-doc 按后者搜不到):`pageQuery`/`pageQueryTotal` 同一套入参:
`fdate`/`fno`/`wbNo`/`hno`/`fdep`(始发站)/`location`/`clearNormal`/`fid`;比出港仓库还少
`agentCode`/`spCode`/`dest`——设计稿筛选的代理/特码/运单类型/业务类型/品名(中) **5 项均无入参**
(缺口 #25);分项统计与 clearNormal 过滤待实测同 #24(记为 #26);详情复用
`IntImpSearch/detail`Body 传 `prefix`+`no`,出参 `data.maWb` 无 schema字段 key 以平板绑定为准:
`awbPc`/`awbWeight`/`cashWeight`/`inPc`/`inWeight`/`lockState`(0/1 需转中文)/`mftStatus` 原始舱单/
`tallyStatus` 理货报告/`command` 海关放行/`by1` 承运人/`dlvTime` 出库时间;`dep`/`dest1`/`dest`/
`unNumber`/`opDate` 为按出港推断,待实测 #27
- `IntImpPickUpDlv`提取出库2026-07-31 文档核对):`pageQuery` 入参含 **`outState`
0 未出库/1 已出库)**——待出库/已出库 Tab 直接真实过滤(抓包证实携带,效果待内网 A/B #29
另有 `fno`/`dest`/`origin`/`carrier`/`awbType`/`businessType`/`goods`/`likeNo`/`pkId`/
`beginDate`/`endDate`+`dateType`(0 入库/1 离港)/`chargeFlag`(0 未提取/1 已提取)
**无 `fdate`(航班日期)入参**(缺口 #28);出参无车牌/目的港/业务类型名称(#28
运单号筛选参数名是 **`no`**(平板既有口径);`chargeName`/`chargeTime` = 柜台办理人/缴费(提取)时间,
`dlvTime` = 出库时间,`dlvName` 按提货人语义推断作「出库人」展示(待确认 #29
确认出库接口 `pickUpOut` 文档注明**需将全字段传至后端**(平板 `selectedItems.toRequestBody()` 已满足)
- `IntImpSearch`进港查询2026-07-31 文档核对):`pageQuery`/`pageQueryTotal` 分页参数名是
**`page`/`limit`**(不是 pageNum/pageSize手机筛选 9 项入参全部真实存在:`beginDate`/`endDate`/
`fno`/`agentCode`/`spCode`/`origin`(始发站)/`awbType`/`businessType`/`goods`(品名,**不是 goodsCn**
`outState`0 未出库/1 已出库)文档为 integer前端传字符串靠 Jackson 隐式转换;`pageQueryTotal`
出参无已入库/已出库分项计数(缺口 #30手机三格统计为客户端计数口径dlvTime 非空=已出库、
inDate 非空=已入库);出参含 `agentName`(中文名)+ `agentCode`agentName 可为 null
- 「进港移库」(设计稿 11**归属更正2026-08-03 用户确认):属国内进港移库 `DomImpMove`**
不是国际进港移库——「后端模块缺失」的旧结论(原缺口 #31)作废,原按 IntExpMove 约定预接的
IntImpMove 前端实现已整体删除。溯源api-doc 53 模块中移库仅 `DomImpMove`国内进港8 接口)与
`IntExpMove`国际出港4 接口移库按转关业务前缀划分DomImpMove 处理 `CI**`、IntExpMove
处理 `IO**`),设计稿详情卡的「国际进港」红标签实为 `awbType` 值(如「国际进港(国内中转)」),
不代表页面归属
- `DomImpMove`国内进港移库2026-08-03 内网实测):手机 Tab 双端点——待移库 `search` /
已移库 `searchMoved`(同一套入参 schema分页参数名 **`page`/`limit`**);入参 A/B 实测:
**`wbNo``awbType`(值为 CICO/CIII/CIIO 转关码)过滤生效;`fdate`/`fno`/`spCode` 文档有定义但
被静默忽略**(缺口 #32`searchMoved`/`detail` 出参 **`opId`/`opDate` 恒 null** 且无操作人姓名
字段(缺口 #33,移库人/移库时间显示"-"`moveId` 形如 `CICO240617155016` 疑似内嵌移库时间戳但无
文档语义;`searchMoved` 出参**无 pic 三字段**search 有)——拍照上传页统一先调 `GET detail`
回填已有照片(#34 前端已规避);照片提交走 `modify` 最小体
`{mawbId, remark, picNumber, pic, originalPic}`平板移交编辑页同链路removeEmptyOrNull
批量移库 `move` 入参 `{fid:"0", ids:[mawbId]}`;国内进港特码字典
`DictUtils.getSpecialCodeList(flag=0, ieFlag="I")` 实测取数正常
- `IntExpCheckIn`出港计重2026-07-29 内网实测):`likeNo` **并非任意模糊**——按 8 位 `no`
匹配11 位 wbNo 或部分号均 0 条11 位全号必须走 `wbNo``checkIn`/`checkInList`
文档有定义但 `pageQuery`/`pageQueryTotal` **均静默忽略**(缺口 #12,待计重/计重中计数依赖);
查询入参无通道号/承运人/运单类型(#13)、`checked/*` 无收运时间范围(#14`checked/pageQuery`
出参无通道号(#15)但有 `userName`(计重人中文名);`listRecordByWh` 出参计重人仅 `opId`#16
`preArrive` 成功后 `pageQuery``arriveFlag` 不回填(#17`splitCheckIn`/`completeCheckIn`
`palletNumber`/`carWeight` 入参(#18,手机版托盘数量/自重按设计稿传预留参数);
运单类型字典:`DictUtils.getWaybillTypeList2(ieFlag="E", type="IO")`
## 内网直调验证技巧(比驱动 UI 快得多)
登录态 token 存在 SharedPreference 里,取出后可以直接 curl 后端做行为验证
**注意:不要把 token 打印到输出里**,落临时文件引用):
```bash
adb -s <serial> shell "run-as com.lukouguoji.aerologic cat \
/data/data/com.lukouguoji.aerologic/shared_prefs/data.xml" \
| grep -o '<string name="token">[^<]*' | sed 's/.*>//' > /tmp/air_token
curl -s -X POST "http://192.168.1.250:8093/IntExpOutHandover/pageQuery" \
-H "Authorization: $(cat /tmp/air_token)" -H "Content-Type: application/json" \
-d '{"pageNum":1,"pageSize":50,"handoverState":0}'
```
用它做「参数是否生效」的 A/B 对比(同条件只改一个参数看 total 变化),
再回 App UI 走一遍确认端到端链路。UI 里的滚轮日期选择器可用
`input swipe`(慢速 500ms、每次 3 格 ≈ 396px驱动滑完截图校准。