Files
aerologic-app/documents/双端合入主干交接文档.md
YANG JIANKUAN 388d605869 docs: 新增双端合入主干交接文档,修正 CLAUDE.md 过期信息
- documents/双端合入主干交接文档.md:分支状态、平板/手机开发状态、合并内容、
  开发规则、验证覆盖、待决事项与注意事项
- CLAUDE.md:版本 1.8.7 (87);JDK 17 运行 / Java 1.8 编译目标;模拟器路径与
  AVD 名(AeroLogic_Phone sw=394dp / AeroLogic_Tablet);运抵长按浮层与已删除的
  补充信息页;分支约定处链接交接文档

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 23:10:45 -07:00

17 KiB
Raw Blame History

平板 + 5.5 寸手机合入主干后的交接

日期:2026-10-11 | 基线提交:origin/main @ 131eb03 | 在线版:https://claude.ai/artifact/N8cWdTcMAzk9N86NSPevTC

本文描述合并当天的状态。分支、版本号等信息如有变化,以仓库为准。

接手前先知道这几件事

  1. 只有一条开发分支:main。 手机适配分支 feature/phone-ui-adaptation 已于 2026-10-11 合入,平板和 5.5 寸手机以后都在 main 上一起开发。
  2. 业务以平板为准,手机只做界面。 两端共用 ViewModel、接口、表单项、筛选入参和默认值;差异只能出现在布局(View)层。
  3. 同一个页面有两份同名布局:res/layout-sw600dp/ 是平板,res/layout/ 是手机。改平板页面时要同时检查手机布局和这个页面的所有弹框。
  4. 有两件事等人拍板:ULD 保存可能报 500(问题清单 #36),以及手机独有的几个界面功能留不留(见第 6 节)。

1. 仓库与分支

分支 / 位置 提交 状态 建议
origin/main 131eb03 唯一开发分支 以后所有开发从这里拉分支、合回这里。
本地 main(主 checkout ~/Development/Projects/aerologic-app) 871fa4c 落后 30 个提交 合并是在另一个 worktree 里推送的,主 checkout 还没同步。到那个目录执行 git pull --ff-only。
feature/phone-ui-adaptation(本地 + 远端) 42647c2 已完整合入 不要再往上提交。确认无人使用后可以删除(删除远端分支前先跟团队确认)。
worktree/phone-adaptation(仅本地) 42647c2 已完整合入 可删除。
merge/phone-into-main(仅本地,worktree ~/.herdr/worktrees/aerologic-app/worktree-phone-adaptation 当前检出) 131eb03 与 main 相同 合并时用的临时分支。可以 git worktree remove 这个 worktree 后删除分支。

合并提交 131eb03 的第一父提交是原 main(871fa4c),第二父提交是手机分支(42647c2),所以 git log --first-parent main 仍然是平板的历史。两条线的分叉点是 9c4588e:分叉后 main 有 58 个平板提交,手机分支有 29 个提交,合并时共 45 个文件冲突。

2. 平板与手机的开发状态

平板(10 寸横屏)

  • 功能完整,即合并前 main 上的全部功能。
  • 合并没有改平板的业务逻辑。冲突的平板布局用三方合并放进了 layout-sw600dp/,内容就是 main 最新版。
  • 已有手机变体的页面:20 个 Activity 布局 + 11 个弹框布局在 layout-sw600dp/。
  • 其余平板页面(舱单、理货、组装、航班管理等)只有一份布局,放在 res/layout/,没有手机版。

手机(5.5 寸竖屏)

  • 设计稿 01~11 的 11 个入口全部完成,并已按 main 的新平板功能补齐(见第 3 节)。
  • 手机首页是 module_p 的 PDAEnterActivity,菜单是手写清单(GjViewModel / GnViewModel),按登录权限串过滤。
  • 设计参考:documents/5.5寸手持端设计文件/,技术方案 documents/5.5寸手持端适配技术方案.md。

手机已适配页面

首页入口 页面(Activity) 模块 说明
国际 · 出港移库 IntExpMoveActivity、IntExpMoveEditActivity gjc 详情 / 编辑与平板共用同一个 Activity,手机布局为「运单详情」样式。
国际 · 出库交接 IntExpOutHandoverActivity、IntExpOutHandoverDetailActivity gjc 底部栏带「允许装机」「配运」次按钮。
国际 · 出港计重 GjcWeighingListActivity、GjcWeighingStartActivity、GjcWeighingRecordListActivity、GjcWeighingRecordDetailsActivity gjc 另有手机专属 GjcWeighingWbDetailActivity(运单详情)。
国际 · 出港运抵 IntExpArriveActivity gjc 手机专属 IntExpArriveSubOrderActivity(分单明细)、IntExpArriveReceiptActivity(分单回执);主单回执用两端共用的 CustomsResponseActivity。
国际 · 出港查询 GjcQueryActivity、GjcQueryDetailsActivity、LogDetailActivity(运单追踪) gjc / app
国际 · 出港仓库 IntExpStorageUseActivity gjc 平板的「勾选 + 底部批量」在手机上改为卡片四按钮:清仓 / 修改库位 / 出库 / 入库。
国际 · 进港仓库 IntImpStorageUseActivity、IntImpQueryDetailsActivity gjj 接口前缀是 IntImpStorage,不是 IntImpStorageUse。
国际 · 进港查询 IntImpQueryActivity gjj
国际 · 提取出库 IntImpPickUpDLVActivity gjj 手机专属 IntImpPickUpDetailActivity。
国际 · ULD 管理 UldListActivity、UldEditActivity app 一套编辑布局覆盖新增 / 修改 / 详情。
国内 · 进港移库 GnjMoveStashListActivity app 业务归属国内进港移库(DomImpMove)。手机专属 GnjMoveStashDetailActivity、GnjMoveStashPhotoActivity。

手机首页还有一批旧的 PDA 竖屏入口(国际:普货收运、板箱组装、板箱过磅、进港理货;国内:出港收运、出港复磅、出港存放、进港卸机、货物转运、转运记录、事故签证、单证交接)。它们是 module_p 原有页面,不在这次设计稿范围内,合并没有改动,也没有验证。

3. 这次合并做了什么

冲突处理原则

  • 布局:平板布局取 main 最新版,三方合并进 layout-sw600dp/,没有冲突残留。手机布局保留原样,再逐页补上 main 新增的业务字段和操作。
  • Bean / ViewModel:一律取平板逻辑。手机只保留它额外需要的展示字段(如 opUserDisplay、统计字段)。
  • Manifest:取手机分支版本(屏幕方向统一为 unspecified),再补上 main 新增的 Activity。

main 的平板功能同步到手机

页面 同步到手机的内容
出港运抵 卡片显示海关放行、运单类型;筛选加分单号;回执改走平板同一接口和回执页;长按菜单加「删除申报」(手机底部弹框)。
出库交接 卡片显示装机状态;底部栏加「允许装机」「配运」;配运弹框做了手机变体。
出港移库 详情和编辑改用平板的 IntExpMoveEditActivity,删除手机专属 IntExpMoveDetailActivity;卡片加「编辑」;筛选加卸货站。
出港 / 进港仓库 清仓弹框加备注,卡片显示清仓备注;入库、出库弹框可填件数和重量(出库弹框新做了手机变体);进港卡片件数取 pcLabel。
开始计重 ViewModel 整体取平板版本:加运单号、地磅重量、平板车、托盘信息,运抵重量按平板公式自动计算;航班日期 / 航班号 / 航程可编辑。
计重 / 计重记录 计重列表加「新增」按钮;计重记录加航班号筛选,卡片加「运抵申报」入口。
计重明细 重量与托盘自重按平板逻辑联动(和恒定),同时保留手机的输入原文处理(避免光标跳动)。
进港查询 筛选加出库状态。
ULD 采用平板的来源列表与 HFE 默认值;卡片显示所在港 / 位置。

手机按平板收敛的地方(使用上能感觉到)

  • 删除了平板不传的查询入参:likeNo(8 位运单号模糊查询)、进港移库的航班日期 / 航班号 / 特码、出港移库的特码。
  • 恢复平板默认查询值:计重、计重记录、提取出库等页面默认查当天,首次打开常常是空列表,属于预期行为。
  • 补齐平板有而手机缺的筛选项:运抵分单号、进港查询出库状态、计重记录航班号、进港移库承运人、出港移库卸货站。
  • ULD 编辑去掉平板没有的「进港航班号」和手机额外加的必填校验(影响见 #36)。

4. 以后怎么开发

项目根目录的 CLAUDE.md「5.5 寸手持端双形态适配规范」一节是完整规范,.claude/skills/phone-adapt/ 是手机适配流程。下面是最常用的几条。

布局双变体的硬性约束

  • 两个变体文件同名:平板 layout-sw600dp/xxx.xml,手机 layout/xxx.xml。禁止用 xxx_phone.xml 加代码判断,那样会生成另一个 Binding 类,进页面就 ClassCastException。
  • 两个变体的 <variable> 名称和类型必须一致。
  • Kotlin 里引用的控件 id 两边都要有;只有一边有的 id 在 Binding 里是可空的,代码里要写 binding.xxx?.。
  • 弹框同样做双变体,并在构造参数里切换位置:BaseDialogModel(if (DeviceUtil.isPhone()) DIALOG_TYPE_BOTTOM else DIALOG_TYPE_CENTER)。
  • Manifest 新 Activity 的 screenOrientation 写 unspecified,由 BaseActivity 按设备锁方向。

平板改了一个已适配页面,标准步骤

  1. 改平板布局(layout-sw600dp/)和 ViewModel。
  2. 打开同名手机布局(layout/),补上同样的字段、筛选项和操作入口。平板的批量按钮在手机上可以改成卡片按钮或 PhoneBottomBar 的次按钮(subAction1Text / subAction2Text)。
  3. 检查这个页面用到的每一个 DialogModel,新弹框要做手机变体。
  4. 手机 Tab 角标、计数这类只有手机用的额外请求,放在 phoneExtrasEnabled 一类的开关后面,不能改变平板的请求。
  5. 两台模拟器各走一遍,再编译 ./gradlew assembleDebug。

手机端不能做的事

  • 不能新增平板没有的查询入参(后端口径:手机筛选一律与平板一致,后端不认识的参数会被静默忽略)。
  • 不能改写平板的默认查询值(如默认当天)。
  • 不能少平板的表单项或校验,也不能多加平板没有的校验。

新做一个手机页面

按 CLAUDE.md「手机版页面改造步骤」:git mv 平板布局到 layout-sw600dp/ → 写同名手机布局 → 优先复用 module_base/.../ui/weight/phone/ 下的组件(PhoneSearchBar、PhoneFormRow、PhoneBottomBar 等)→ 到 GjViewModel / GnViewModel 加首页菜单入口(最容易忘,忘了在手机上就进不去)。

5. 已验证与未验证

验证环境:手机模拟器 AeroLogic_Phone(720×1440,API 31,sw=394dp),平板模拟器 AeroLogic_Tablet(1280×800,sw=800dp),连内网测试服务。

项目 结果 说明
Debug 编译 ✅ 通过 合并后 assembleDebug 成功。
手机 11 个入口主流程 ✅ 已验证 列表、Tab、筛选、详情、弹框打开,无崩溃。
平板回归(已适配的页面) ✅ 已验证 主要页面打开、筛选、弹框,无崩溃,布局为 main 最新版。
开始计重自动计算 ✅ 已验证 地磅 500、托盘 2 个 × 18 → 运抵重量 464,与平板公式一致。新增模式头部不再显示 "null kg"。
手机新弹框(出库 / 入库 / 清仓 / 配运 / 删除申报) ⚠️ 只打开过 样式和字段都确认了,没有点提交,以免改动测试数据。
所有写操作(申报、出入库、清仓、保存、移库、拍照上传) ⚠️ 未提交验证 合并后没有真实提交过。建议用测试数据逐个点一次提交,平板和手机都要。
海关回执页有内容时的显示 ❌ 未验证 测试数据里没有带回执的运单。
ULD 管理、国内进港移库 ❌ 只编译过 合并后的改动没在模拟器上点过。
手机首页旧 PDA 入口 ❌ 未验证 不在本次范围。
Release 包、真机(交付手持机 / 平板) ❌ 未验证 只在模拟器上跑过 Debug 包。

6. 已知问题与待决事项

需要决定

  • ULD 保存可能报 500(问题清单 #36)。 后端 saveUld 在缺少最大装载容积 / 最大载重时返回 500。之前只有手机做了必填拦截;按「以平板为准」去掉之后,两端都可能报错。可选做法:让后端修,或者在平板加同样的必填校验(再同步到手机)。

  • 手机独有的界面功能目前保留。 它们只在手机上发请求,不影响平板,所以合并时留下了:

    • 各列表的「待 / 已」Tab,以及 Tab 角标额外发的统计请求;
    • 进港移库「已移库」Tab(调用平板不用的 searchMoved 接口);
    • 出港运抵分单明细页、分单回执页;ULD 状态显示为「可用 / 维修」;ULD 入库时间保存时补 00:00:00。

    如果要求两端严格一致,需要逐项删除。

对用户的行为变化(属于预期)

  • 手机列表默认查当天,首次打开常常为空,要在筛选里清掉日期。
  • 手机输入 8 位运单号不再能模糊查到(去掉了 likeNo),和平板一致。

后端缺口(问题清单 #35~#41,待后端处理)

  • ULD 列表按 uld 搜索返回 500;saveUld 缺 maxVolume / maxWeight 返回 500(#36)。
  • IntImpStorage/pageQuery 列表过滤全部不生效。
  • 出港仓库列表与统计的口径不一致。
  • 已移库数据没有 mawbId,无法补传照片。

完整内容和每一项的后端答复在 documents/后端接口对接问题清单.xlsx。这份表是和后端对接的正式文档,新发现的缺口要继续记在里面。

其他待办

  • PhoneSearchBar 还没接 AutoQuery 联想(AutoQueryManager 只接了平板组件)。

7. 容易踩的坑

  1. API 文档的 token 提交进了仓库。 .mcp.json 里写着 api-doc MCP 的 Authorization: Bearer …,并且已被 git 跟踪。建议轮换这个 token,改为从环境变量或本地未跟踪的配置读取。
  2. 换行符混用,没有 .gitattributes。 main 原有文件多为 CRLF,手机分支新建的文件是 LF。编辑时保持文件原有换行符,否则会出现整文件 diff,合并和 review 都会很难看。
  3. 没有手机变体的平板页面,在手机上会直接显示平板布局。 给手机首页加入口前,必须先做手机布局。
  4. 后端会静默忽略不认识的参数。 猜错参数名会得出「后端不支持」的误判。入参出参一律用 api-doc MCP 核对,流程见 .claude/skills/phone-adapt/references/api-doc.md。
  5. XML 里 ?? 兜底不生效。 网络层会把 JSON null 转成空串,?? 只判断 null。要在 Bean 上写计算属性(如 agentDisplay、opUserDisplay)。
  6. RecyclerView 里给 item 设 GONE 不会收起高度。 Tab 过滤要在数据层过滤后整体 refresh。
  7. Intent 传递的 Bean 里 @Transient 字段会变成 null(checked、showMore 等)。接收方要 .map { it.copy() }。
  8. 同页多个手机复合组件会串状态。 新写同类组件要覆写 dispatchSaveInstanceState / dispatchRestoreInstanceState(见 CLAUDE.md)。

第 5~8 条在 CLAUDE.md「常见编译错误速查」里都有详细说明和修复方式。

8. 环境与工具

  • 工具链:Gradle 用 Java 17 运行(mise.toml),编译目标是 Java 1.8;当前版本 1.8.7(versionCode 87)。
  • 内网:测试服务器在内网,模拟器要在内网环境下才能拉到数据,否则提示「接口访问失败」。测试账号向项目负责人索取(不写在文档里)。
  • 登录不保留:冷启动后要重新登录。
  • Debug 直达页面:app/src/debug/AndroidManifest.xml 把适配页设为 exported,可以直接拉起(只在 Debug 包生效)。
  • 平板模拟器没有物理按键,adb shell monkey 拉起会失败,改用 am start。
  • 手机模拟器上软键盘弹出时按返回键,有时会被吞掉并退出到桌面,不是崩溃。
  • mobile-mcp 偶尔识别不到 emulator-5554,可以直接用 adb。
# 启动模拟器(模拟器可执行文件在 Homebrew 的 android-commandlinetools 下)
/opt/homebrew/share/android-commandlinetools/emulator/emulator -avd AeroLogic_Phone &
/opt/homebrew/share/android-commandlinetools/emulator/emulator -avd AeroLogic_Tablet &

# 编译安装
./gradlew assembleDebug
adb -s emulator-5554 install -r app/build/outputs/apk/debug/*.apk

# 拉起登录页(平板没有物理键时用这个)
adb -s emulator-5556 shell am start -n com.lukouguoji.aerologic/com.lukouguoji.module_base.LoginActivity

# 确认设备形态识别
adb -s emulator-5554 logcat -d -s BaseActivity:D    # PHONE(sw=394dp) / TABLET(sw=800dp)

9. 关键文件索引

文件 用途
CLAUDE.md 项目规范总入口,包括双形态适配规范、分支约定、常见错误速查。
CHANGELOG.md [Unreleased] 下「手机适配分支合入主干 · 2026-10-11」是本次合并的完整记录。
documents/后端接口对接问题清单.xlsx 与后端对接的正式问题清单(#1~#41)。
documents/5.5寸手持端设计文件/ 手机设计稿(HTML)。
.claude/skills/phone-adapt/ 手机适配流程,含 api-doc、组件、平板安全、验证等参考。
module_base/.../util/DeviceUtil.kt 手机 / 平板判定(sw ≥ 600dp 为平板)。
module_base/.../ui/weight/phone/ 手机公共组件,适配器在 PhoneWidgetKtx.kt。
module_base/.../MyApplication.kt AutoSize 设计基准(手机竖屏 390×844,平板横屏 1152×720)。
module_p/.../ui/enter/gj/GjViewModel.kt、gn/GnViewModel.kt 手机首页国际 / 国内菜单清单。
app/.../HomeFragment.kt 平板首页菜单,手机入口的权限串和路由要以它为准。