feat(phone): 5.5 寸手持端首页按新设计稿改版

按 documents/5.5寸首页新样式/ 设计稿还原 PDAEnterActivity 四个 Tab(仅 module_p,平板不经过该页):

- 国内/国际 Tab:分组标题栏 + 三列宫格(PdaMenuGroup / PdaMenuRenderer),分组与顺序按设计稿;
  20 个入口换新图标(源 GIF/PNG 转 PNG 放 drawable-nodpi,放 xxhdpi 会先缩后放发糊),
  设计稿未覆盖的入口追加到组尾沿用旧图标
- 权限过滤 authList.contains(key) 与改版前逐字一致:ADMIN 账号入口集合改版前后 diff 为空
  (国内 9、国际 12),21 个入口逐个点击跳转目标不变
- 首页航班动态:卡片 + 国内/国际、进港/出港分段 + 日期卡片(‹ › 翻日)+ 浅色表格 + 设置悬浮钮;
  默认方向改为进港,日期统一补零,日期选择器从当前选中日期打开
- 底部 Tab 栏(16dp 图标与文字居中)、消息铃铛与角标(四个 Tab 统一位置、切换不再移动)、
  状态栏 #3B71E8;「我的」顶栏同步新导航栏样式;首页 AutoSize 基准 400 → 390
- 删除 module_p 中不再引用的旧菜单/Tab 图标副本
- CLAUDE.md / phone-adapt skill 更新首页菜单入口说明,补图标发糊、分段控件描边与取整两个坑

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
YANG JIANKUAN
2026-10-21 13:37:04 +08:00
parent a909f96d61
commit 542c35b22d
107 changed files with 3173 additions and 528 deletions

View File

@@ -1012,9 +1012,11 @@ Manifest 写死 `userLandscape` 时,即使 `BaseActivity` 在 `super.onCreate`
| 国内 | `GnViewModel` | `module_p/.../ui/enter/gn/` |
| 国际 | `GjViewModel` | `module_p/.../ui/enter/gj/` |
**菜单项是手写清单,不是接口下发**。权限机制只做过滤:登录返回的权限串存在
`SharedPreferenceUtil.getString(Constant.Share.authList)`(一个逗号分隔的长字符串),
菜单项按 `authList.contains(bean.key)` 决定显不显示。
**菜单项是手写清单,不是接口下发**。登录接口只下发「分组 → 权限码」(`auths`,形如
`{"IntExp":["AppIntExpCheckWeighing",…],"Supervision":[…]}`,存在
`SharedPreferenceUtil.getString(Constant.Share.authList)`),菜单名称/图标/跳转在平板和手机上都是前端写死的映射。
手机端菜单项按 `authList.contains(bean.key)` 决定显不显示(`PdaMenuGroup.kt` 的 `filterByAuth()`,
**2026-10-21 首页改版时刻意保持与改版前逐字一致**,保证同一账号的入口集合不变)。
所以「适配完页面但手机首页看不到入口」的原因通常**不是没权限,而是清单里没加**。
排查顺序:先确认权限串里有对应 key,再去看清单。
@@ -1025,25 +1027,43 @@ adb -s <serial> shell "run-as com.lukouguoji.aerologic \
cat /data/data/com.lukouguoji.aerologic/shared_prefs/data.xml" | tr ',' '\n' | grep -oE "App[A-Za-z]+" | sort -u
```
加一项就是加一行 —— `ActionBean` 的第 4 个参数填 ARouter 路由即可,无需写 when 分支
**2026-10-21 起首页按 `documents/5.5寸首页新样式/` 设计稿改版**:清单按设计稿分组
(`PdaMenuGroup(标题, 入口列表)`,如国际 Tab =「国际出港 / 国际进港 / 综合管理」),
由 `PdaMenuRenderer` 渲染成「分组标题栏 + 三列宫格」,过滤后为空的分组整组隐藏。
**分组口径以设计稿为准,不是接口的 auths 分组**(例如单证交接/转运记录在接口里属 Supervision,
设计稿放在「国内出港」)。
加一项就是在对应分组里加一行 —— `ActionBean` 的第 4 个参数填 ARouter 路由即可,无需写 when 分支
(`module_p` 只依赖 `module_base`,看不到 `module_gjc` 等业务模块,跨模块只能走路由):
```kotlin
ActionBean(
"出港移库",
R.drawable.gjc_yi_ku_icon, // 图标复用 Pad 端同款
Constant.AuthName.GjcYiKuListActivity, // 权限串,与 Pad 端菜单保持一致
ARouterConstants.ACTIVITY_URL_INT_EXP_MOVE // 有 route 就走通用跳转
PdaMenuGroup(
"国际出港", listOf(
ActionBean(
"出港移库",
R.drawable.img_pda_menu_gjc_move, // 设计稿新版宫格图标
Constant.AuthName.GjcYiKuListActivity, // 权限串,与 Pad 端菜单保持一致
ARouterConstants.ACTIVITY_URL_INT_EXP_MOVE // 有 route 就走通用跳转
),
…
)
),
```
两点注意:
注意:
- **权限串与路由都要和 Pad 端菜单对齐**:以 `app/.../HomeFragment.kt` 里该权限对应的
`ARouter.build(...)` 为准。同一业务常有新旧两个 Activity(如移库的 `GjcYiKuListActivity`
与 `IntExpMoveActivity`),Pad 菜单实际跳的才是要适配的那个
- **图标**:`module_p` 看不到 `module_gjc` 的资源,把 Pad 图标 PNG 复制一份到
`module_p/src/main/res/drawable-xxhdpi/`(该模块既有 4 个图标就是这么放的,同名不同密度桶可共存)
- **图标**:设计稿图标源文件在 `documents/5.5寸首页新样式/icons/`(约 167px 方图,自带「国际/国内」角标),
统一转 PNG(源文件多为单帧 GIF,GIF 只有 256 色 + 1 位透明,不进资源)后放
`module_p/src/main/res/drawable-nodpi/img_pda_menu_*.png`,按 59.7dp 宫格居中裁剪 + 圆角显示。
**必须放 nodpi,不能放 xxhdpi**:167px 放 xxhdpi 会在 ~295dpi 设备上解码时先缩到 ≈103px,再被拉伸到
宫格的 110px,实测明显发糊;nodpi 原尺寸解码、由固定尺寸 ImageView 一次缩小,与浏览器渲染设计稿一致
**设计稿没有的入口追加到所属分组末尾、沿用旧图标**(如「板箱过磅」`gjc_fu_bang_icon`)
- **改动清单后核对入口集合**:登录后分别在「国内 / 国际」Tab 用 `ui_probe.sh texts`(需滚动)导出入口名,
与改动前 `LC_ALL=C sort` 后 diff(CJK 文本不加 `LC_ALL=C` 排序不稳定,会 diff 出假差异)。
ADMIN 测试账号基线:国内 9 个、国际 12 个
**示例:状态 Tab 零 ViewModel 改动**(`IntExpMoveActivity` 已实现)
@@ -1313,6 +1333,8 @@ adb shell am start -n com.lukouguoji.aerologic/com.lukouguoji.gjc.activity.IntEx
| 布局构建报 `Error: The string "--" is not permitted within comments` | XML 注释中出现连续双横线(如写"兜底 \"--\""),XML 规范禁止 | 注释里改用文字描述(如「兜底双横线」),代码绑定表达式中的 `"--"` 不受影响 |
| 多选页手机版点「全选」后底部「已选 N 项」不更新(单卡勾选正常) | 批量勾选在 `checkAllClick` 里直接 set,不走 FlowBus 的单卡 EVENT_CHECK_CHANGED 事件,`selectedCountText` 只在事件回调里更新 | `checkAllClick` 末尾自行同步 `selectedCountText`(平板布局不绑定该字段,无影响) |
| 手机版数字输入框(`PhoneFormRow` 双向绑 Double 的 `xxxStr`)输入 "18" 变成 "81" | getter 由 Double 反推字符串("1" → "1.0"),与输入框文本不等触发 `setText`,光标回到开头 | Bean 里保留输入原文(`@Transient` 私有 String),getter 优先返回原文(参考 `GjcCheckInRecord.trayTotalWeightStr`) |
| 固定 dp 尺寸显示的位图图标在手机上发糊(设计稿里很清晰) | 位图放进了比「源像素 ÷ 显示 dp」更高的密度桶(如 167px 的宫格图放 xxhdpi,在 ~295dpi 设备上解码先缩到 103px,再拉伸到 110px 显示) | 只按固定 dp 尺寸显示的设计稿位图放 `drawable-nodpi`(原尺寸解码,View 一次缩小);排查:截图放大对比设计稿,算 `源px × 设备dpi / 桶dpi` 是否小于显示 px |
| 分段/胶囊控件里选中块上下不居中(上窄下宽) | 设计稿 CSS 的 `border` 计入盒子尺寸,而 Android shape 的 `stroke` 画在 background 上、不占 padding——照抄 CSS 的 `padding: 2px` 少了 1dp 描边 | 容器 padding = CSS padding + border 宽度(如 2 + 1 = 3dp),且容器高度用 `wrap_content`——写死 28dp 时 28/3/22dp 各自取整成 px,内框比选中块少 1px,选中块底边被截;用像素列取色(`magick … txt:-`)量上下间隙验证 |
| XML 里 `bean.a ?? bean.b` 兜底不生效,字段明明有值却显示占位符 | 网络层转换器把 JSON null 归一成空串 `""`,DataBinding 的 `??` 只判 null 不判空串,永远取到左侧的空串 | 在 Bean 上加计算属性做 `isNullOrEmpty` 双兜底(如 `agentDisplay`),XML 绑计算属性(进港查询/出港查询代理人已踩过) |
---