Files
aerologic-app/.claude/skills/phone-adapt/references/api-doc.md
YANG JIANKUAN d9dc927525 fix(gjj): 国际事故签证「发现时间」改为下拉选择,数据源 POST typeCode/searchDateType
- Api 新增 getSearchDateTypeList(POST 无参,返回 code 1~8 + 中英文 name),
  与同路径的 GET 通用字典 getDictList 区分
- 编辑页 DATE → SPINNER,与 Web 端一致提交字典 name
- 历史数据(日期值、带尾随换行的 name)不在字典内时补进下拉列表,
  避免编辑/详情回显为空、保存时被清掉
- phone-adapt api-doc 记录该接口 GET/POST 语义

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:29:33 -07:00

17 KiB
Raw Blame History

api-doc MCP:接口定义核对流程(阶段 2 必读)

适配页面前,所有用到的接口都要在 api-doc(AgentFox)里核对一遍入参/出参, 不要靠平板代码或猜测推断参数名——出库交接就因为猜了 hoState(实际是 handoverState) 白白折腾了一轮实机排查。

连接方式

项目 .mcp.json 已配置 api-doc 远程 HTTP MCP。若会话内 MCP 工具可直接调用 (mcp__api-doc__*),直接用;若工具没有注入会话(ToolSearch 搜不到),用 curl 走 MCP 协议手工调用,三步:

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" 返回空数组)
  • typeCode/searchDateType:同一路径两个接口——GET ?code=xxx 是通用字典(Api.getDictList), POST 无参是「发现时间类型」(Api.getSearchDateTypeList,出参 code 1~8 + name 中英文时机); 国际事故签证 seachDate 与 Web 端一致存 name(历史数据另有 2026-09-24 日期值与带 \r\n 的 name)
  • 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 打印到输出里,落临时文件引用):

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)驱动,滑完截图校准。

2026-10-09 后端反馈联调后的最新口径(与上文冲突时以本节为准)

后端在问题清单补「解决方案」后逐项内网实测的结论。通用规则:后端对手机端新增筛选维度一律答复 「与平板端查询参数保持一致」——手机筛选只放平板已用的入参;文档里定义了但平板没用的入参, 多数实测也被忽略(agentCode/spCode/dest/opId 等),别再按文档加筛选。

  • 统一统计 DTO:各 */pageQueryTotal 出参现含 uldNumber/storedNumber/departedNumber/ notClearNumber/clearNumber/waitCheckInNumber/checkingNumber/flightNumber(ManifestTotalDto 已补齐)。分项统计一律取出参,不要再按状态入参多调几次 total
  • IntExpOutHandover/pageQueryTotal 已修复(与列表一致);Tab 角标取 uldNumber(板箱数);无交接人入参
  • IntExpMove/pageQuery 出参新增 flight("20260924/MU2222")/businessName/opUserName;已移库 opId/opdate 已回填
  • eqm/uld:状态维持两态;source(空运/陆运) 出参与保存入参支持、查询入参不支持;入库时间 = inStoreTime (date-time,只传日期 400)、所在港 = nowPort;批删 deleteUldBatch(Body 为字符串数组); ⚠️ pageQuery 带 uld 即 500(#35);saveUld 缺 maxVolume/maxWeight 即 500(#36)
  • IntExpCheckIn:listRecordByWh 出参 opUserName/trayNumber/trayTotalWeight; checked/pageQuery 出参 passageWay;splitCheckIn/completeCheckIn 托盘入参 = trayNumber + trayTotalWeight(数量×自重);arriveFlag 已回填("0" 正常/"1" 提前运抵); ⚠️ pageQuery 的 checkIn 过滤仍被忽略(#40,统计用分项出参);checked/pageQuery 的 dest/opId 被忽略
  • IntExpArrive:入参 arrivalStatus("0" 未运抵/"1" 已运抵)服务端过滤生效;agentCode 被忽略;补充信息页已删除
  • IntExpSearch:beginDate/endDate 只有携带 dateState(0 入库/1 离港)才生效;outState 生效
  • IntExpStorageUse:仅 fdate/fno/wbNo/location/clearNormal 有意义;⚠️ 列表 total 与统计 wbNumber 不一致(#38)
  • IntImpStorage:⚠️ pageQuery 当前所有过滤条件均失效(#37),pageQueryTotal 正常
  • IntImpSearch/detail:按平板展示 航程 range(无经停站)/unNumber/lockState/出库时间 dlvTime
  • IntImpPickUpDlv:运单号入参用 wbNo;出参新增 refUserName(出库人姓名,dlvName 是提货人);测试环境暂无数据
  • DomImpMove:fdate/fno/spCode 已生效;searchMoved 已回填 opId/opDate/opUserName; 新增 GET movedDetail?moveId=(含 pic 三字段);⚠️ 已移库运单无 mawbId,modify 无法补传照片(#39)