feat: 完成出港运抵页面5.5寸手机端适配

- 主列表新增待运抵/已运抵 Tab(客户端按申报状态拆分)+ 卡片长按浮层(补充/重置/回执)
- 新增分单明细页:复用主列表已加载数据,零新增请求
- 新增回执内容只读页
- 新增补充信息页:参照 Pad 端收发货人信息批量应用模式(后端接口暂缺,已登记问题清单)
- 手机首页「国际」Tab 增加「出港运抵」入口
- 修复两个平台坑:RecyclerView 内 GONE 不塌陷高度;Serializable Intent 传递
  遇 @Transient 字段反序列化为 null 导致的崩溃
- 登记后端接口缺口 2 项(#19~#20)至问题清单

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-30 11:44:51 +08:00
parent 1eb288a703
commit ef8e7cfacb
37 changed files with 2825 additions and 775 deletions

View File

@@ -70,6 +70,13 @@ curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \
0 正常/1 故障(三态需求=缺口 #7);无「来源」字段(#8)、无 `checkInDate`/`ifNo` 筛选入参(#9)、 0 正常/1 故障(三态需求=缺口 #7);无「来源」字段(#8)、无 `checkInDate`/`ifNo` 筛选入参(#9)、
无批量删除(#10`deleteUld``@Query` 单条);出参 `ifNo`/`efNo`/`checkInDate`/`checkOutDate` 无批量删除(#10`deleteUld``@Query` 单条);出参 `ifNo`/`efNo`/`checkInDate`/`checkOutDate`
文档无描述,按命名推断进/出港航班号与出入库时间(#11 待确认) 文档无描述,按命名推断进/出港航班号与出入库时间(#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
- `IntExpCheckIn`出港计重2026-07-29 内网实测):`likeNo` **并非任意模糊**——按 8 位 `no` - `IntExpCheckIn`出港计重2026-07-29 内网实测):`likeNo` **并非任意模糊**——按 8 位 `no`
匹配11 位 wbNo 或部分号均 0 条11 位全号必须走 `wbNo``checkIn`/`checkInList` 匹配11 位 wbNo 或部分号均 0 条11 位全号必须走 `wbNo``checkIn`/`checkInList`
文档有定义但 `pageQuery`/`pageQueryTotal` **均静默忽略**(缺口 #12,待计重/计重中计数依赖); 文档有定义但 `pageQuery`/`pageQueryTotal` **均静默忽略**(缺口 #12,待计重/计重中计数依赖);

View File

@@ -130,7 +130,7 @@ binding.btnMove?.setOnClickListener { showMoveConfirmDialog() }
手机「待交接」Tab 下理论上只有未交接记录(服务端按状态过滤),所以全选照原样全量勾选就是对的; 手机「待交接」Tab 下理论上只有未交接记录(服务端按状态过滤),所以全选照原样全量勾选就是对的;
若为此加上「跳过已交接」的过滤,反而改变了平板端(平板列表混排两种状态)的行为。 若为此加上「跳过已交接」的过滤,反而改变了平板端(平板列表混排两种状态)的行为。
## 屏幕方向Manifest 必须写资源引用 ## 屏幕方向Manifest 一律写 `unspecified`
新增 Activity 注册时: 新增 Activity 注册时:
@@ -138,15 +138,20 @@ binding.btnMove?.setOnClickListener { showMoveConfirmDialog() }
<activity android:name="…" <activity android:name="…"
android:configChanges="orientation|keyboardHidden" android:configChanges="orientation|keyboardHidden"
android:exported="false" android:exported="false"
android:screenOrientation="@integer/screen_orientation" /> android:screenOrientation="unspecified" />
``` ```
**不要写死 `userLandscape`。** `screenOrientation` 由系统在创建 Activity 窗口时生效, **两种错误方案都实测踩过,别再试:**
那时业务代码还没跑;写死横屏后即使 `BaseActivity``super.onCreate` 之前改成竖屏 - 写死 `userLandscape` → 手机「先横屏、约 1 秒后转竖屏」(方向在建窗口时就定了
用户也会看到「先横屏、约 1 秒后转竖屏」的闪屏和重建。 `BaseActivity``super.onCreate` 之前纠正也来不及)
-`@integer/screen_orientation` 资源引用(曾经以为是优雅方案)→ **更糟**:系统解析
Manifest 属性不套用设备限定符,所有 Activity 实际都拿到 `values/` 默认值(竖屏),
平板因此先竖后横,且 AutoSize 在竖屏配置下选中平板竖屏 720dp 基准
(正常应为 1152×720 横屏基准),交互几次后整个 UI 放大约 1.6 倍
资源取值:`module_base/res/values/integers.xml` = 1(portrait) `unspecified` 让系统按设备当前物理方向建窗口(平板横屏摆放→横屏起,手机→竖屏起
`values-sw600dp/integers.xml` = 11(userLandscape)。全项目已统一替换。 两端起始方向本就正确),`BaseActivity.applyDeviceOrientation()` 再按形态锁定,
不产生二次纠正。全项目 192 处已统一为 `unspecified`
## 改 module_base 公共代码时 ## 改 module_base 公共代码时
@@ -158,6 +163,81 @@ binding.btnMove?.setOnClickListener { showMoveConfirmDialog() }
- Bean 上加只读计算属性是安全的Gson 只序列化字段,不动 getter - Bean 上加只读计算属性是安全的Gson 只序列化字段,不动 getter
加**字段**要谨慎,会进请求体 加**字段**要谨慎,会进请求体
## RecyclerView 里不要用 item 级 visibility 做 Tab/分类过滤
普通 ViewGroupLinearLayout 等)里 `View.GONE` 的子 View 会自动塌陷为 0 高度、不占布局空间——
**RecyclerView + LinearLayoutManager 不是这样**:它按子项的测量高度参与滚动区域计算,
不会因为子项是 GONE 就跳过。给 item 根节点加 `visibility="@{tab条件 ? VISIBLE : GONE}"`
切 Tab会在列表里留下一段空白隐藏项的高度仍被保留角标数字和实际卡片数量对不上。
出港运抵的「待运抵/已运抵」Tab 就踩了这个坑(实机截图验证:切到「已运抵」后顶部有一大块
空白,隐藏的待运抵卡片高度并未塌陷)。正确做法是在数据层过滤,而不是视图层:
```kotlin
// ViewModel自己维护完整列表不依赖 adapter.items 的历史状态
// 见下一节adapter.items 在 loadMore 场景可能已经是上次过滤后的子集,不能当作真源)
private var allLoadedList: List<GjcMaWb> = emptyList()
override fun getData() {
launchLoadingCollect({ ... }) {
onSuccess = { result ->
val newPageItems = result.list ?: emptyList()
allLoadedList = if (pageModel.page <= 1) newPageItems else allLoadedList + newPageItems
pageModel.handleListBean(result) {
// 无论 handleListBean 内部把 adapter.items 搞成什么样,这里用 allLoadedList
// 强制覆盖为「当前 Tab 的正确子集」,兜底纠正
val filtered = allLoadedList.filter { it.isPending == (currentTab.value == "pending") }
pageModel.rv?.commonAdapter()?.refresh(filtered)
}
}
}
}
fun onTabChangedPhone() {
val filtered = allLoadedList.filter { it.isPending == (currentTab.value == "pending") }
pageModel.rv?.commonAdapter()?.refresh(filtered) // 只是 items.clear()+addAll()+notifyDataSetChanged无副作用
}
```
`CommonAdapter.refresh()` 只是替换内部列表并 `notifyDataSetChanged()`,不影响
SmartRefreshLayout 的分页/完成状态,可以放心在 `handleListBean` 回调里再调用一次。
## Intent 传递 Serializable Bean`@Transient` 字段反序列化后是 null
`GjcMaWb`/`GjcHaWb``checked`/`showMore`/`actionMenuVisible` 三个 UI 状态字段都标了
`@Transient`(本意是避免 Gson 把 `ObservableBoolean` 的内部结构序列化进网络请求体)。
但 Kotlin 的 `@Transient` 注解生成的就是 JVM 的 `transient` 修饰符,这个修饰符对 **Java
对象序列化**`Intent.putExtra(String, Serializable)` 走的正是这条路径)有实际含义:
反序列化时会跳过 `transient` 字段的恢复,对象引用类型的字段结果就是 **null**
新增手机专属页面时,如果要把 `List<GjcHaWb>` 通过 `ArrayList<GjcHaWb>` 塞进 `Intent`
传给下一个页面接收方拿到的对象「看起来」字段都对wbNo、pc、weight 这些正常字段没问题,
因为它们不是 `@Transient`),但只要调用 `bean.checked.set(...)` 就会立刻崩溃:
```
NullPointerException: Attempt to invoke virtual method
'void androidx.databinding.ObservableBoolean.set(boolean)' on a null object reference
```
出港运抵的「分单明细」页第一版全选按钮就是这样崩的。**修复只需一行**,在接收方
`initOnCreated` 里对拿到的列表整体 `.copy()` 一遍——`.copy()` 会重新触发一次真正的对象构造,
类体里 `val checked = ObservableBoolean(false)` 这类初始化逻辑跟着重新跑一遍,
把 null 补成全新实例:
```kotlin
@Suppress("UNCHECKED_CAST")
fun initOnCreated(intent: Intent) {
val list = intent.getSerializableExtra(Constant.Key.DATA) as? ArrayList<GjcHaWb>
// .copy() 补上被 Java 序列化跳过的 @Transient 字段
fullList = (list ?: emptyList()).map { it.copy() }
}
```
这个坑只在「Intent 传递 Serializable Bean + 接收方要切换 checked/showMore 等状态」时才会
触发;纯只读展示(如回执页)不调用这些字段的 setter不会崩但补一道 `.copy()` 无害,
建议只要通过 Intent 传了 haWbList/maWbList 就统一加上,别等下次踩到才想起来。
## 已知的既有问题(不是你改坏的) ## 已知的既有问题(不是你改坏的)
`am start` 直启页面时,若**先经过首页**再启目标页,会崩在 `am start` 直启页面时,若**先经过首页**再启目标页,会崩在

View File

@@ -8,6 +8,37 @@
## [Unreleased] ## [Unreleased]
### 新增 (Added) ### 新增 (Added)
- 「出港运抵」5.5 寸手机端适配(主列表 + 3 个手机专属新页,设计稿 04_出港运抵
主列表 `IntExpArriveActivity` 新增「待运抵/已运抵」Tab客户端按 declareStatus 是否为空拆分数据集,
接口无此查询参数)+ 卡片长按浮层(待运抵→补充、已运抵→重置+回执,纯 UI 长按)+ 底部全选/已选/申报
(仅待运抵 Tab 显示,选中范围独立于 Pad 全量选择逻辑);新增「分单明细」`IntExpArriveSubOrderActivity`
(数据直接复用主列表已加载的 haWbList零新增请求长按单条重置 + 底部批量申报);新增「回执内容」
`IntExpArriveReceiptActivity`(只读页,复用 haWbList[].response + arrivalOpDate新增「补充信息」
`IntExpArriveSupplementActivity`(参照 Pad 端国际进港「收发货人信息」批量应用模式,对整个运单的
haWbList 批量应用同一份表单,后端接口不存在,已实机确认 404见问题清单 #19
- 手机首页「国际」Tab 增加「出港运抵」入口
- `GjcMaWb`/`GjcHaWb` 新增 `isPending`/`declareTagColor`/`haWbTagColor`/`arrivalOpDateText`
手机版专属计算属性;`GjcHaWb` 补充 `Serializable` 实现(供 Intent 跨页传递分单列表)
- 新增手机版资源:`bg_phone_tag_indigo`/`bg_phone_tag_amber`(申报状态三色标签)、
`bg_phone_fab_purple`/`bg_phone_fab_amber`/`bg_phone_fab_green`(长按浮层圆形操作按钮)
- 后端缺口 2 项登记问题清单 #19~#20分单补充信息保存接口不存在、Tab 无申报状态查询参数)
### 修复 (Fixed)
- **RecyclerView + Tab 过滤新坑**:给 item 根节点加 `visibility="@{...}"` 切 Tab 会在列表里
留下空白——RecyclerView/LinearLayoutManager 不像普通 ViewGroup 那样让 GONE 子项自动塌陷为
0 高度。改为在 ViewModel 数据层维护完整列表Tab 切换时把过滤后的子集整体 `refresh()`
adapter已实机截图验证空白消失、卡片数与角标一致
- **Serializable Intent + @Transient 崩溃新坑**`GjcMaWb`/`GjcHaWb``checked` 等 UI 状态
字段标了 `@Transient`(避免 Gson 序列化 ObservableBoolean但这同时是 JVM `transient`
修饰符Java 序列化Intent 传递机制)会跳过其恢复,反序列化后为 null切换选中状态时
NullPointerException 崩溃。修复:接收方 `initOnCreated` 对列表 `.map { it.copy() }` 重新
触发类体初始化补上(已实机崩溃复现并验证修复)
### 验证 (Verified)
- 出港运抵双端实机验证通过:手机端 Tab 切换(角标/卡片双向正确)/全选/单选/长按菜单/查看分单
/分单明细全选与长按重置/补充信息(真实数据回填+下拉字典+提交请求体完整+后端404如实呈现/
回执页 全链路 crash=0、方向无闪屏平板端布局与交互4 搜索条+分单内嵌展开+底部 5 元素操作栏)
与改造前逐项一致
- 「出港计重」5.5 寸手机端适配(首个全链路 4+1 页模块,设计稿 03_出港计重 - 「出港计重」5.5 寸手机端适配(首个全链路 4+1 页模块,设计稿 03_出港计重
待计重列表(三格统计 总票数/待计重/计重中 + 卡片状态标签 未计重/计重中 + 卡片内单票「提前运抵」+ 待计重列表(三格统计 总票数/待计重/计重中 + 卡片状态标签 未计重/计重中 + 卡片内单票「提前运抵」+
FAB 进计重记录 + 筛选弹层 通道号/承运人/运单类型/代理人)、开始计重(头部预配统计卡 + PhoneFormRow 表单, FAB 进计重记录 + 筛选弹层 通道号/承运人/运单类型/代理人)、开始计重(头部预配统计卡 + PhoneFormRow 表单,

View File

@@ -1110,6 +1110,18 @@ override fun dispatchRestoreInstanceState(container: SparseArray<Parcelable>) =
isEditMode 复用为手机全屏「修改记录」覆层)+ 手机专属新页 `GjcWeighingWbDetailActivity`(运单详情)。 isEditMode 复用为手机全屏「修改记录」覆层)+ 手机专属新页 `GjcWeighingWbDetailActivity`(运单详情)。
搜索分流规则实测含字母→fno、11 位数字→wbNo、其余→likeNolikeNo 按 8 位 no 匹配并非模糊); 搜索分流规则实测含字母→fno、11 位数字→wbNo、其余→likeNolikeNo 按 8 位 no 匹配并非模糊);
checkIn 过滤等 7 项后端缺口见问题清单 #12~#18 checkIn 过滤等 7 项后端缺口见问题清单 #12~#18
- 「出港运抵」主列表 + 3 个手机专属新页:`IntExpArriveActivity`(待运抵/已运抵 Tab客户端按
`declareStatus` 是否为空拆分数据集,卡片长按浮层:待运抵→补充、已运抵→重置+回执)、
`IntExpArriveSubOrderActivity`(分单明细,数据直接复用主列表已加载的 `haWbList`,零新增请求)、
`IntExpArriveReceiptActivity`(回执内容只读页,复用 `haWbList[].response`)、
`IntExpArriveSupplementActivity`(补充信息,参照 Pad 端国际进港「收发货人信息」批量应用模式,
后端接口不存在,实机 404 已确认,见问题清单 #19)。
Tab 过滤两个坑:① **RecyclerView 里 `View.GONE` 不会让 item 塌陷为 0 高度**(不同于普通
ViewGroup必须在数据层整体 `refresh()` 过滤后的子集给 adapter不能给 item 根节点加
visibility 绑定(实机截图验证过,见「常见编译错误速查」);② 通过 `Intent.putExtra(Serializable)`
传递的 `GjcHaWb`/`GjcMaWb`,其 `checked`/`showMore`/`actionMenuVisible` 字段标了
`@Transient`= JVM `transient`Java 序列化会跳过),反序列化后为 null直接
`.checked.set(...)` 会崩溃——接收方 `initOnCreated` 必须对列表 `.map { it.copy() }` 补上
-**待办** -**待办**
- `PhoneSearchBar` 接入 AutoQuery 联想(`AutoQueryManager` 目前只对接了 Pad 系组件) - `PhoneSearchBar` 接入 AutoQuery 联想(`AutoQueryManager` 目前只对接了 Pad 系组件)
- 出库交接 Tab 角标恒 0`IntExpOutHandover/pageQueryTotal` 出参恒 0后端缺陷问题清单 #6 - 出库交接 Tab 角标恒 0`IntExpOutHandover/pageQueryTotal` 出参恒 0后端缺陷问题清单 #6
@@ -1202,6 +1214,8 @@ adb shell am start -n com.lukouguoji.aerologic/com.lukouguoji.gjc.activity.IntEx
| 手机版筛选项默认值(如日期)自动被清空 | 多个复合自定义 View 内部子控件 id 相同,系统按 id 恢复状态时跨实例串档 | 组件重写 `dispatchSaveInstanceState`/`dispatchRestoreInstanceState``dispatchFreezeSelfOnly`/`dispatchThawSelfOnly`(见「手机版公共组件库」) | | 手机版筛选项默认值(如日期)自动被清空 | 多个复合自定义 View 内部子控件 id 相同,系统按 id 恢复状态时跨实例串档 | 组件重写 `dispatchSaveInstanceState`/`dispatchRestoreInstanceState``dispatchFreezeSelfOnly`/`dispatchThawSelfOnly`(见「手机版公共组件库」) |
| 手机上页面先横屏再转竖屏(闪一下) | Manifest 写死 `screenOrientation="userLandscape"`,系统建窗口时已按横屏,代码纠正为时已晚 | 改成 `android:screenOrientation="unspecified"`,由 `BaseActivity` 按形态锁定(见「屏幕方向」小节) | | 手机上页面先横屏再转竖屏(闪一下) | Manifest 写死 `screenOrientation="userLandscape"`,系统建窗口时已按横屏,代码纠正为时已晚 | 改成 `android:screenOrientation="unspecified"`,由 `BaseActivity` 按形态锁定(见「屏幕方向」小节) |
| 平板先竖屏再转横屏 + 交互后 UI 放大约 1.6 倍 | Manifest 用了 `@integer/screen_orientation` 资源引用;系统解析 Manifest 不套用限定符全部取到竖屏值AutoSize 随之选了平板竖屏 720dp 基准 | Manifest 改回 `unspecified`(见「屏幕方向」小节的 ⛔ 说明) | | 平板先竖屏再转横屏 + 交互后 UI 放大约 1.6 倍 | Manifest 用了 `@integer/screen_orientation` 资源引用;系统解析 Manifest 不套用限定符全部取到竖屏值AutoSize 随之选了平板竖屏 720dp 基准 | Manifest 改回 `unspecified`(见「屏幕方向」小节的 ⛔ 说明) |
| Tab/分类切换后列表顶部留一大块空白,卡片数量却不对 | 给 item 根节点加了 `visibility="@{tab条件 ? VISIBLE : GONE}"`——RecyclerView/LinearLayoutManager 不会像普通 ViewGroup 那样让 GONE 的子项自动塌陷为 0 高度,仍按测量高度参与滚动区域计算 | 不要用 item 级 visibility 做过滤;在 ViewModel 里自行维护完整列表Tab 切换时把过滤后的子集整体 `commonAdapter()?.refresh(filteredList)` 给 adapter |
| 通过 `Intent.putExtra(Serializable)` 传递的 Bean切换其 `checked`/`showMore` 等状态时崩溃 `NullPointerException: ... on a null object reference` | 这些字段标了 `@Transient`= JVM `transient`,本意是避免 Gson 网络请求序列化 `ObservableBoolean`),但 Java 对象序列化Intent 传递走的机制)会跳过 `transient` 字段的恢复,反序列化后是 null | 接收方 `initOnCreated` 里对列表做 `.map { it.copy() }`——`.copy()` 会重新走一遍类体初始化逻辑,用全新 `ObservableBoolean(false)` 补上 |
--- ---

View File

@@ -80,5 +80,29 @@
android:exported="true" android:exported="true"
tools:replace="android:exported" /> tools:replace="android:exported" />
<!-- 出港运抵(手机版适配验证页) -->
<activity
android:name="com.lukouguoji.gjc.activity.IntExpArriveActivity"
android:exported="true"
tools:replace="android:exported" />
<!-- 出港运抵-分单明细(手机版适配验证页) -->
<activity
android:name="com.lukouguoji.gjc.activity.IntExpArriveSubOrderActivity"
android:exported="true"
tools:replace="android:exported" />
<!-- 出港运抵-回执内容(手机版适配验证页) -->
<activity
android:name="com.lukouguoji.gjc.activity.IntExpArriveReceiptActivity"
android:exported="true"
tools:replace="android:exported" />
<!-- 出港运抵-补充信息(手机版适配验证页) -->
<activity
android:name="com.lukouguoji.gjc.activity.IntExpArriveSupplementActivity"
android:exported="true"
tools:replace="android:exported" />
</application> </application>
</manifest> </manifest>

View File

@@ -145,6 +145,24 @@
android:configChanges="orientation|keyboardHidden" android:configChanges="orientation|keyboardHidden"
android:exported="false" android:exported="false"
android:screenOrientation="unspecified" /> android:screenOrientation="unspecified" />
<!-- 国际出港运抵-分单明细5.5寸手机版专属页面) -->
<activity
android:name="com.lukouguoji.gjc.activity.IntExpArriveSubOrderActivity"
android:configChanges="orientation|keyboardHidden"
android:exported="false"
android:screenOrientation="unspecified" />
<!-- 国际出港运抵-回执内容5.5寸手机版专属页面) -->
<activity
android:name="com.lukouguoji.gjc.activity.IntExpArriveReceiptActivity"
android:configChanges="orientation|keyboardHidden"
android:exported="false"
android:screenOrientation="unspecified" />
<!-- 国际出港运抵-补充信息5.5寸手机版专属页面) -->
<activity
android:name="com.lukouguoji.gjc.activity.IntExpArriveSupplementActivity"
android:configChanges="orientation|keyboardHidden"
android:exported="false"
android:screenOrientation="unspecified" />
<!-- 国际出港仓库 --> <!-- 国际出港仓库 -->
<activity <activity
android:name="com.lukouguoji.gjc.activity.IntExpStorageUseActivity" android:name="com.lukouguoji.gjc.activity.IntExpStorageUseActivity"

View File

@@ -1,6 +1,7 @@
package com.lukouguoji.module_base.bean package com.lukouguoji.module_base.bean
import androidx.databinding.ObservableBoolean import androidx.databinding.ObservableBoolean
import java.io.Serializable
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
@@ -122,12 +123,31 @@ data class GjcMaWb(
val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态 val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态
@Transient @Transient
val showMore: ObservableBoolean = ObservableBoolean(false) // 展开状态 val showMore: ObservableBoolean = ObservableBoolean(false) // 展开状态
@Transient
val actionMenuVisible: ObservableBoolean = ObservableBoolean(false) // 5.5寸手机版:卡片长按操作浮层显隐
// 兼容现有API的isSelected属性 // 兼容现有API的isSelected属性
var isSelected: Boolean var isSelected: Boolean
get() = checked.get() get() = checked.get()
set(value) = checked.set(value) set(value) = checked.set(value)
/**
* 5.5寸手机版是否处于「待运抵」Tab申报状态为空
* 接口无按申报状态区分的查询参数Tab 由客户端对已加载数据拆分。
*/
val isPending: Boolean
get() = declareStatus.isNullOrEmpty()
/**
* 5.5寸手机版申报状态三色标签的着色分类01=绿/W=靛蓝/其余非空=琥珀)。
*/
val declareTagColor: String
get() = when (declareStatus) {
"01" -> "green"
"W" -> "indigo"
else -> if (declareStatus.isNullOrEmpty()) "" else "amber"
}
// ==================== 状态转换扩展属性 ==================== // ==================== 状态转换扩展属性 ====================
/** /**
* 计重状态中文 * 计重状态中文
@@ -277,15 +297,36 @@ data class GjcHaWb(
var tallyOpId: String? = null, // 理货操作人ID var tallyOpId: String? = null, // 理货操作人ID
var declareCount: Long? = null, // 申报次数 var declareCount: Long? = null, // 申报次数
var activeId: Long? = null // 活动ID var activeId: Long? = null // 活动ID
) { ) : Serializable {
// ==================== UI扩展字段 ==================== // ==================== UI扩展字段 ====================
@Transient @Transient
val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态 val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态
@Transient
val actionMenuVisible: ObservableBoolean = ObservableBoolean(false) // 5.5寸手机版:卡片长按操作浮层显隐
// 兼容现有API的isSelected属性 // 兼容现有API的isSelected属性
var isSelected: Boolean var isSelected: Boolean
get() = checked.get() get() = checked.get()
set(value) = checked.set(value) set(value) = checked.set(value)
/**
* 5.5寸手机版申报状态三色标签的着色分类01=绿/W=靛蓝/其余非空=琥珀)。
* 与 GjcMaWb.declareTagColor 同源逻辑,作用于分单自身的 arrivalStatus。
*/
val haWbTagColor: String
get() = when (arrivalStatus) {
"01" -> "green"
"W" -> "indigo"
else -> if (arrivalStatus.isNullOrEmpty()) "" else "amber"
}
/**
* 5.5寸手机版「回执」页:运抵操作时间(格式化)。
*/
val arrivalOpDateText: String
get() = arrivalOpDate?.let {
SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(it)
} ?: ""
} }
/** /**

View File

@@ -851,6 +851,16 @@ interface Api {
@POST("IntExpArrive/deleteDeclare") @POST("IntExpArrive/deleteDeclare")
suspend fun deleteArriveDeclare(@Body data: RequestBody): BaseResultBean<Boolean> suspend fun deleteArriveDeclare(@Body data: RequestBody): BaseResultBean<Boolean>
/**
* 国际出港运抵-分单补充收发货人信息5.5寸手机版新增)
*
* 后端暂无此接口api-doc 搜索 IntExpArrive、HaWb 均无匹配),路径为参照 Pad 端国际进港
* IntImpAirManifest/complete 命名习惯拟定的建议值,见 documents/后端接口对接问题清单.xlsx。
* 请求体为分单数组,仅需 haWbId 与收发货人相关字段。
*/
@POST("IntExpArrive/haWb/supplement")
suspend fun supplementArriveHaWb(@Body data: RequestBody): BaseResultBean<Any>
/** /**
* 国际出港移库-分页查询 * 国际出港移库-分页查询
* 接口路径: /IntExpMove/pageQuery * 接口路径: /IntExpMove/pageQuery

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 手机版圆形操作按钮:琥珀色(出港运抵卡片长按菜单「重置」) -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#F59E0B" />
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 手机版圆形操作按钮:翠绿色(出港运抵卡片长按菜单「回执」) -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#10B981" />
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 手机版圆形操作按钮:紫色(出港运抵卡片长按菜单「补充」) -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#A855F7" />
</shape>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 手机版状态标签:琥珀底(出港运抵申报状态 E与 bg_phone_tag_green/indigo/gray 同属状态标签家族 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/phone_tag_amber_bg" />
<corners android:radius="6dp" />
</shape>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 手机版状态标签:靛蓝底(出港运抵申报状态 W与 bg_phone_tag_green/orange/gray 同属状态标签家族 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/phone_tag_indigo_bg" />
<corners android:radius="6dp" />
</shape>

View File

@@ -75,5 +75,9 @@
<color name="phone_tag_orange_text">#EA580C</color> <color name="phone_tag_orange_text">#EA580C</color>
<color name="phone_danger_bg">#FEE2E2</color> <!-- 危险操作按钮-浅红底ULD管理批量删除 --> <color name="phone_danger_bg">#FEE2E2</color> <!-- 危险操作按钮-浅红底ULD管理批量删除 -->
<color name="phone_danger_text">#DC2626</color> <color name="phone_danger_text">#DC2626</color>
<color name="phone_tag_indigo_bg">#E0E7FF</color> <!-- 状态标签-靛蓝底(出港运抵申报状态 W -->
<color name="phone_tag_indigo_text">#6366F1</color>
<color name="phone_tag_amber_bg">#FEF3C7</color> <!-- 状态标签-琥珀底(出港运抵申报状态 E -->
<color name="phone_tag_amber_text">#D97706</color>
</resources> </resources>

View File

@@ -3,6 +3,7 @@ package com.lukouguoji.gjc.activity
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.databinding.ObservableBoolean
import com.alibaba.android.arouter.facade.annotation.Autowired import com.alibaba.android.arouter.facade.annotation.Autowired
import com.alibaba.android.arouter.facade.annotation.Route import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter import com.alibaba.android.arouter.launcher.ARouter
@@ -10,15 +11,24 @@ import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.databinding.ActivityIntExpArriveBinding import com.lukouguoji.gjc.databinding.ActivityIntExpArriveBinding
import com.lukouguoji.gjc.viewModel.IntExpArriveViewModel import com.lukouguoji.gjc.viewModel.IntExpArriveViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.bean.GjcHaWb
import com.lukouguoji.module_base.bean.GjcMaWb
import com.lukouguoji.module_base.common.Constant import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.common.ConstantEvent import com.lukouguoji.module_base.common.ConstantEvent
import com.lukouguoji.module_base.impl.FlowBus import com.lukouguoji.module_base.impl.FlowBus
import com.lukouguoji.module_base.impl.observe import com.lukouguoji.module_base.impl.observe
import com.lukouguoji.module_base.ktx.addOnItemClickListener import com.lukouguoji.module_base.ktx.addOnItemClickListener
import com.lukouguoji.module_base.ktx.commonAdapter
import com.lukouguoji.module_base.router.ARouterConstants import com.lukouguoji.module_base.router.ARouterConstants
import com.lukouguoji.module_base.util.DeviceUtil
import java.util.ArrayList
/** /**
* 国际出港-出港运抵页面 * 国际出港-出港运抵页面
*
* 布局 id 不区分设备,平板/手机由资源限定符自动选择:
* layout-sw600dp/activity_int_exp_arrive.xml平板
* layout/activity_int_exp_arrive.xml手机
*/ */
@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE) @Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE)
class IntExpArriveActivity : class IntExpArriveActivity :
@@ -31,12 +41,25 @@ class IntExpArriveActivity :
override fun layoutId() = R.layout.activity_int_exp_arrive override fun layoutId() = R.layout.activity_int_exp_arrive
override fun viewModelClass() = IntExpArriveViewModel::class.java override fun viewModelClass() = IntExpArriveViewModel::class.java
/** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */
val filterPanelVisible = ObservableBoolean(false)
/** 供 [com.lukouguoji.gjc.holder.IntExpArriveViewHolder] 绑定 item 布局的 viewModel 变量(父类 viewModel 为 protected */
val itemViewModel: IntExpArriveViewModel get() = viewModel
override fun initOnCreate(savedInstanceState: Bundle?) { override fun initOnCreate(savedInstanceState: Bundle?) {
// 注入 ARouter 参数 // 注入 ARouter 参数
ARouter.getInstance().inject(this) ARouter.getInstance().inject(this)
setBackArrow("国际出港运抵") setBackArrow("国际出港运抵")
binding.viewModel = viewModel binding.viewModel = viewModel
binding.activity = this
// 手机版专属数据:加载「代理」筛选下拉
// 平板端不调用,查询链路与请求次数与改造前完全一致
if (DeviceUtil.isPhone()) {
viewModel.initPhoneExtras()
}
// 如果有传入运单号,自动填充并触发搜索 // 如果有传入运单号,自动填充并触发搜索
if (!wbNoParam.isNullOrEmpty()) { if (!wbNoParam.isNullOrEmpty()) {
@@ -63,6 +86,77 @@ class IntExpArriveActivity :
} }
} }
// ==================== 手机版专用交互(纯 UI复用既有 ViewModel 字段与数据) ====================
/**
* 手机版 Tab 切换回调PhoneStatusTab 已通过双向绑定写入 viewModel.currentTab
* 这里触发 ViewModel 把适配器数据集替换为过滤后的子集(不发起新请求)。
*/
fun onArriveTabChanged() {
viewModel.onTabChangedPhone()
}
/** 卡片长按展开操作浮层View.OnLongClickListener 要求返回 Boolean */
fun showCardActionPhone(bean: GjcMaWb): Boolean {
bean.actionMenuVisible.set(true)
return true
}
/** 点击浮层遮罩/空白处:收起操作浮层 */
fun hideCardActionPhone(bean: GjcMaWb) {
bean.actionMenuVisible.set(false)
}
/** 选择圈勾选状态变化后回调(由 ViewHolder 调用) */
fun onItemCheckChanged() {
viewModel.onItemCheckChanged()
}
/** 手机版筛选弹层显隐切换 */
fun toggleFilterPanel() {
filterPanelVisible.set(!filterPanelVisible.get())
}
/** 手机版筛选:重置 */
fun resetFilter() {
viewModel.flightDate.value = ""
viewModel.flightNo.value = ""
viewModel.agentCodePhone.value = ""
}
/** 手机版筛选:确认 */
fun confirmFilter() {
filterPanelVisible.set(false)
viewModel.searchClick()
}
/**
* 进入「分单明细」页:直接传递该运单已加载的 haWbList零新增请求。
*/
fun openSubOrder(bean: GjcMaWb) {
val list = ArrayList<GjcHaWb>(bean.haWbList.orEmpty())
IntExpArriveSubOrderActivity.start(this, bean.wbNo.orEmpty(), list)
}
/**
* 进入「回执」页(手机专属只读页):复用 haWbList[].response + arrivalOpDate零新增请求。
*/
fun openReceipt(bean: GjcMaWb) {
bean.actionMenuVisible.set(false)
val list = ArrayList<GjcHaWb>(bean.haWbList.orEmpty())
IntExpArriveReceiptActivity.start(this, bean.wbNo.orEmpty(), list)
}
/**
* 进入「补充信息」页(手机专属新页):对该运单整个 haWbList 批量应用(参照 Pad 端国际进港
* IntArrSupplementInfoViewModel 的批量复制模式)。后端暂无保存接口,见接口问题清单。
*/
fun openSupplement(bean: GjcMaWb) {
bean.actionMenuVisible.set(false)
val list = ArrayList<GjcHaWb>(bean.haWbList.orEmpty())
IntExpArriveSupplementActivity.start(this, bean.wbNo.orEmpty(), list)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
when (requestCode) { when (requestCode) {

View File

@@ -0,0 +1,43 @@
package com.lukouguoji.gjc.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.databinding.ActivityIntExpArriveReceiptBinding
import com.lukouguoji.gjc.viewModel.IntExpArriveReceiptViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.bean.GjcHaWb
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.ktx.refresh
/**
* 国际出港运抵-回执内容页5.5寸手机版专属只读新页,平板端无对应页面)
*
* 数据来自主列表页已加载的 haWbList零新增请求。
* 对应设计稿 documents/5.5寸手持端设计文件/04_出港运抵/receipt.html。
*/
class IntExpArriveReceiptActivity :
BaseBindingActivity<ActivityIntExpArriveReceiptBinding, IntExpArriveReceiptViewModel>() {
override fun layoutId() = R.layout.activity_int_exp_arrive_receipt
override fun viewModelClass() = IntExpArriveReceiptViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("回执内容")
binding.viewModel = viewModel
viewModel.initOnCreated(intent)
viewModel.receiptList.observe(this) { binding.rv.refresh(it) }
}
companion object {
@JvmStatic
fun start(context: Context, wbNo: String, haWbList: ArrayList<GjcHaWb>) {
val starter = Intent(context, IntExpArriveReceiptActivity::class.java)
.putExtra(Constant.Key.CODE, wbNo)
.putExtra(Constant.Key.DATA, haWbList)
context.startActivity(starter)
}
}
}

View File

@@ -0,0 +1,92 @@
package com.lukouguoji.gjc.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.databinding.ObservableBoolean
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.databinding.ActivityIntExpArriveSubOrderBinding
import com.lukouguoji.gjc.viewModel.IntExpArriveSubOrderViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.bean.GjcHaWb
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.ktx.commonAdapter
import com.lukouguoji.module_base.ktx.refresh
/**
* 国际出港运抵-分单明细页5.5寸手机版专属新页,平板端无对应页面)
*
* 数据来自主列表页已加载的 haWbListIntent 传入),零新增请求。
* 对应设计稿 documents/5.5寸手持端设计文件/04_出港运抵/suborder.html。
*/
class IntExpArriveSubOrderActivity :
BaseBindingActivity<ActivityIntExpArriveSubOrderBinding, IntExpArriveSubOrderViewModel>() {
override fun layoutId() = R.layout.activity_int_exp_arrive_sub_order
override fun viewModelClass() = IntExpArriveSubOrderViewModel::class.java
/** 筛选弹层显隐(仅 UI 状态) */
val filterPanelVisible = ObservableBoolean(false)
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("分单明细")
binding.viewModel = viewModel
binding.activity = this
viewModel.initOnCreated(intent)
// 监听数据变化刷新列表
viewModel.displayList.observe(this) { binding.rv.refresh(it) }
}
/** 子项选中状态变化后回调(由 ViewHolder 调用) */
fun onItemCheckChanged() {
viewModel.onItemCheckChanged()
}
/** 全选按钮点击切换全部选中状态后强制刷新列表checked 为原地修改,不触发 LiveData */
fun checkAllClick() {
viewModel.checkAllClick()
binding.rv.commonAdapter()?.notifyDataSetChanged()
}
/** 卡片长按展开操作浮层View.OnLongClickListener 要求返回 Boolean */
fun showActionMenu(bean: GjcHaWb): Boolean {
bean.actionMenuVisible.set(true)
return true
}
/** 点击浮层遮罩:收起操作浮层 */
fun hideActionMenu(bean: GjcHaWb) {
bean.actionMenuVisible.set(false)
}
/** 长按菜单「重置」(单条) */
fun resetSingleClick(bean: GjcHaWb) {
bean.actionMenuVisible.set(false)
viewModel.resetSingleClick(bean)
}
fun toggleFilterPanel() {
filterPanelVisible.set(!filterPanelVisible.get())
}
fun resetFilter() {
viewModel.hnoFilter.value = ""
}
fun confirmFilter() {
filterPanelVisible.set(false)
viewModel.searchClick()
}
companion object {
@JvmStatic
fun start(context: Context, wbNo: String, haWbList: ArrayList<GjcHaWb>) {
val starter = Intent(context, IntExpArriveSubOrderActivity::class.java)
.putExtra(IntExpArriveSubOrderViewModel.KEY_WB_NO, wbNo)
.putExtra(Constant.Key.DATA, haWbList)
context.startActivity(starter)
}
}
}

View File

@@ -0,0 +1,41 @@
package com.lukouguoji.gjc.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.databinding.ActivityIntExpArriveSupplementBinding
import com.lukouguoji.gjc.viewModel.IntExpArriveSupplementViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.bean.GjcHaWb
import com.lukouguoji.module_base.common.Constant
/**
* 国际出港运抵-补充信息页5.5寸手机版专属新页,平板端无对应页面)
*
* 参照 Pad 端国际进港「收发货人信息」补充页的批量应用模式:对该运单整个 haWbList 批量应用
* 同一份收发货人表单。后端暂无保存接口,见 IntExpArriveSupplementViewModel 顶部注释。
* 对应设计稿 documents/5.5寸手持端设计文件/04_出港运抵/supplement.html。
*/
class IntExpArriveSupplementActivity :
BaseBindingActivity<ActivityIntExpArriveSupplementBinding, IntExpArriveSupplementViewModel>() {
override fun layoutId() = R.layout.activity_int_exp_arrive_supplement
override fun viewModelClass() = IntExpArriveSupplementViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("补充信息")
binding.viewModel = viewModel
viewModel.initOnCreated(intent)
}
companion object {
@JvmStatic
fun start(context: Context, wbNo: String, haWbList: ArrayList<GjcHaWb>) {
val starter = Intent(context, IntExpArriveSupplementActivity::class.java)
.putExtra(Constant.Key.CODE, wbNo)
.putExtra(Constant.Key.DATA, haWbList)
context.startActivity(starter)
}
}
}

View File

@@ -0,0 +1,19 @@
package com.lukouguoji.gjc.holder
import android.view.View
import com.lukouguoji.gjc.databinding.ItemIntExpArriveReceiptBinding
import com.lukouguoji.module_base.base.BaseViewHolder
import com.lukouguoji.module_base.bean.GjcHaWb
/**
* 国际出港运抵-回执内容列表 ViewHolder5.5寸手机版专属只读页)
*/
class IntExpArriveReceiptViewHolder(view: View) :
BaseViewHolder<GjcHaWb, ItemIntExpArriveReceiptBinding>(view) {
override fun onBind(item: Any?, position: Int) {
val bean = getItemBean(item) ?: return
binding.bean = bean
binding.executePendingBindings()
}
}

View File

@@ -0,0 +1,32 @@
package com.lukouguoji.gjc.holder
import android.view.View
import com.lukouguoji.gjc.activity.IntExpArriveSubOrderActivity
import com.lukouguoji.gjc.databinding.ItemIntExpArriveSubOrderBinding
import com.lukouguoji.module_base.base.BaseViewHolder
import com.lukouguoji.module_base.bean.GjcHaWb
/**
* 国际出港运抵-分单明细列表 ViewHolder5.5寸手机版专属页面)
*
* 选中状态变化只影响本页自身的 ViewModel不复用全局 FlowBus.EVENT_CHECK_CHANGED
* 避免与主列表页共享同一事件、产生跨页面的无意义联动)。
*/
class IntExpArriveSubOrderViewHolder(view: View) :
BaseViewHolder<GjcHaWb, ItemIntExpArriveSubOrderBinding>(view) {
override fun onBind(item: Any?, position: Int) {
val bean = getItemBean(item) ?: return
val activity = itemView.context as? IntExpArriveSubOrderActivity
binding.bean = bean
binding.activity = activity
binding.executePendingBindings()
// 整卡点击切换选择状态
binding.ll.setOnClickListener {
bean.checked.set(!bean.checked.get())
activity?.onItemCheckChanged()
binding.executePendingBindings()
}
}
}

View File

@@ -2,6 +2,7 @@ package com.lukouguoji.gjc.holder
import android.view.View import android.view.View
import com.lukouguoji.gjc.R import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.activity.IntExpArriveActivity
import com.lukouguoji.gjc.databinding.ItemIntExpArriveBinding import com.lukouguoji.gjc.databinding.ItemIntExpArriveBinding
import com.lukouguoji.module_base.adapter.setCommonAdapter import com.lukouguoji.module_base.adapter.setCommonAdapter
import com.lukouguoji.module_base.base.BaseViewHolder import com.lukouguoji.module_base.base.BaseViewHolder
@@ -12,52 +13,73 @@ import com.lukouguoji.module_base.ktx.refresh
/** /**
* 国际出港-出港运抵 列表项ViewHolder * 国际出港-出港运抵 列表项ViewHolder
*
* item 布局分平板layout-sw600dp/item_int_exp_arrive.xml内嵌分单子列表 rv_sub 展开/收起)
* 与手机layout/item_int_exp_arrive.xml分单改为独立「分单明细」页无 rv_sub/iv_show 等 id
* 两个变体,单侧独有的 id 在 Binding 基类中为 `@Nullable`,需判空调用。
*/ */
class IntExpArriveViewHolder(view: View) : class IntExpArriveViewHolder(view: View) :
BaseViewHolder<GjcMaWb, ItemIntExpArriveBinding>(view) { BaseViewHolder<GjcMaWb, ItemIntExpArriveBinding>(view) {
override fun onBind(item: Any?, position: Int) { override fun onBind(item: Any?, position: Int) {
val bean = getItemBean(item) ?: return val bean = getItemBean(item) ?: return
val activity = itemView.context as? IntExpArriveActivity
binding.bean = bean binding.bean = bean
binding.position = position binding.position = position
binding.activity = activity
binding.viewModel = activity?.itemViewModel
binding.executePendingBindings() binding.executePendingBindings()
// 添加图标点击事件 - 切换选择状态 // 添加图标点击事件 - 切换选择状态(平板独有)
binding.ivIcon.setOnClickListener { binding.ivIcon?.setOnClickListener {
bean.checked.set(!bean.checked.get()) bean.checked.set(!bean.checked.get())
FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED).tryEmit("check_changed") FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED).tryEmit("check_changed")
binding.executePendingBindings() binding.executePendingBindings()
} }
// 展开按钮点击事件 // 展开按钮点击事件(平板独有)
binding.ivShow.setOnClickListener { binding.ivShow?.setOnClickListener {
bean.showMore.set(!bean.showMore.get()) bean.showMore.set(!bean.showMore.get())
} }
// 选择圈点击事件(手机独有,仅待运抵 Tab 可见)
binding.ivSelect?.setOnClickListener {
bean.checked.set(!bean.checked.get())
activity?.onItemCheckChanged()
binding.executePendingBindings()
}
// 子列表 RecyclerView 仅平板存在,手机版分单改走独立页面
val rvSub = binding.rvSub ?: return
// 初始化子列表 RecyclerView // 初始化子列表 RecyclerView
setCommonAdapter( setCommonAdapter(
binding.rvSub, rvSub,
IntExpArriveSubViewHolder::class.java, IntExpArriveSubViewHolder::class.java,
R.layout.item_int_exp_arrive_sub R.layout.item_int_exp_arrive_sub
) )
// 刷新子列表数据 // 刷新子列表数据
val subList = bean.haWbList ?: emptyList() val subList = bean.haWbList ?: emptyList()
binding.rvSub.refresh(subList) rvSub.refresh(subList)
updateSubListVisibility(subList.isNotEmpty()) updateSubListVisibility(subList.isNotEmpty())
} }
private fun updateSubListVisibility(hasData: Boolean) { private fun updateSubListVisibility(hasData: Boolean) {
val llHeader = binding.llHeader ?: return
val dividerHeader = binding.dividerHeader ?: return
val rvSub = binding.rvSub ?: return
val tvEmpty = binding.tvEmpty ?: return
if (hasData) { if (hasData) {
binding.llHeader.visibility = View.VISIBLE llHeader.visibility = View.VISIBLE
binding.dividerHeader.visibility = View.VISIBLE dividerHeader.visibility = View.VISIBLE
binding.rvSub.visibility = View.VISIBLE rvSub.visibility = View.VISIBLE
binding.tvEmpty.visibility = View.GONE tvEmpty.visibility = View.GONE
} else { } else {
binding.llHeader.visibility = View.GONE llHeader.visibility = View.GONE
binding.dividerHeader.visibility = View.GONE dividerHeader.visibility = View.GONE
binding.rvSub.visibility = View.GONE rvSub.visibility = View.GONE
binding.tvEmpty.visibility = View.VISIBLE tvEmpty.visibility = View.VISIBLE
} }
} }
} }

View File

@@ -0,0 +1,34 @@
package com.lukouguoji.gjc.viewModel
import android.content.Intent
import androidx.lifecycle.MutableLiveData
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.holder.IntExpArriveReceiptViewHolder
import com.lukouguoji.module_base.base.BaseViewModel
import com.lukouguoji.module_base.bean.GjcHaWb
import com.lukouguoji.module_base.common.Constant
/**
* 国际出港运抵-回执内容 ViewModel5.5寸手机版专属只读页)
*
* 数据直接复用主列表页已加载的 haWbList.response / arrivalOpDate 字段,无需任何新增请求。
* 对应设计稿 documents/5.5寸手持端设计文件/04_出港运抵/receipt.html。
*/
class IntExpArriveReceiptViewModel : BaseViewModel() {
val receiptList = MutableLiveData<List<GjcHaWb>>(emptyList())
// 适配器配置
val itemViewHolder = IntExpArriveReceiptViewHolder::class.java
val itemLayoutId = R.layout.item_int_exp_arrive_receipt
@Suppress("UNCHECKED_CAST")
fun initOnCreated(intent: Intent) {
val list = intent.getSerializableExtra(Constant.Key.DATA) as? ArrayList<GjcHaWb>
// .copy() 补上被 Java 序列化跳过的 @Transient 字段checked 等),见分单明细页同款注释
receiptList.value = (list ?: emptyList())
.map { it.copy() }
.filter { !it.response.isNullOrEmpty() }
.sortedByDescending { it.arrivalOpDate }
}
}

View File

@@ -0,0 +1,137 @@
package com.lukouguoji.gjc.viewModel
import android.content.Intent
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.dialog.IntExpArriveResetDialogModel
import com.lukouguoji.gjc.holder.IntExpArriveSubOrderViewHolder
import com.lukouguoji.module_base.base.BaseViewModel
import com.lukouguoji.module_base.bean.GjcHaWb
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.common.ConstantEvent
import com.lukouguoji.module_base.http.net.NetApply
import com.lukouguoji.module_base.impl.FlowBus
import com.lukouguoji.module_base.ktx.launchLoadingCollect
import com.lukouguoji.module_base.ktx.showToast
import com.lukouguoji.module_base.ktx.toRequestBody
import kotlinx.coroutines.launch
/**
* 国际出港运抵-分单明细 ViewModel5.5寸手机版专属页面)
*
* 数据直接复用主列表页已加载的 haWbListIntent 传入),无需任何新增请求。
* 筛选仅「分单号」在客户端生效——航班日期/航班号/代理等字段在单个运单的分单集合内
* 恒为同一值,筛选它们没有实际意义(设计稿疑似沿用主列表筛选组件模板,未按此页场景定制)。
*/
class IntExpArriveSubOrderViewModel : BaseViewModel() {
// 运单号(页面标题辅助展示,非必需)
var wbNo: String = ""
private set
// 完整分单列表Intent 传入,不随筛选变化)
private var fullList: List<GjcHaWb> = emptyList()
// 当前展示列表(按分单号筛选后的结果)
val displayList = MutableLiveData<List<GjcHaWb>>(emptyList())
// 筛选:分单号(客户端 contains 匹配)
val hnoFilter = MutableLiveData("")
// 全选状态与已选计数
val isAllChecked = MutableLiveData(false)
val selectedCount = MutableLiveData("0")
// 适配器配置
val itemViewHolder = IntExpArriveSubOrderViewHolder::class.java
val itemLayoutId = R.layout.item_int_exp_arrive_sub_order
@Suppress("UNCHECKED_CAST")
fun initOnCreated(intent: Intent) {
wbNo = intent.getStringExtra(KEY_WB_NO).orEmpty()
val list = intent.getSerializableExtra(Constant.Key.DATA) as? ArrayList<GjcHaWb>
// Java 序列化会跳过 checked/actionMenuVisible标了 @Transient即 JVM transient 修饰符),
// 反序列化后这两个 ObservableBoolean 字段为 null。.copy() 会重新走一遍类体初始化逻辑,
// 用全新的 ObservableBoolean(false) 补上,避免全选/长按时 NPE已实机崩溃验证过
fullList = (list ?: emptyList()).map { it.copy() }
displayList.value = fullList
}
/**
* 分单号筛选(客户端 contains 匹配,非后端查询)。
*/
fun searchClick() {
val key = hnoFilter.value?.trim().orEmpty()
displayList.value = if (key.isEmpty()) {
fullList
} else {
fullList.filter { it.hno?.contains(key, ignoreCase = true) == true }
}
updateCheckAllStatus()
}
fun onItemCheckChanged() {
updateCheckAllStatus()
}
fun updateCheckAllStatus() {
val list = displayList.value ?: return
isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() }
selectedCount.value = list.count { it.checked.get() }.toString()
}
fun checkAllClick() {
val list = displayList.value ?: return
val shouldCheckAll = !isAllChecked.value!!
list.forEach { it.checked.set(shouldCheckAll) }
isAllChecked.value = shouldCheckAll
selectedCount.value = if (shouldCheckAll) list.size.toString() else "0"
}
/**
* 长按菜单「重置」(单条分单)。
*/
fun resetSingleClick(bean: GjcHaWb) {
val dialog = IntExpArriveResetDialogModel { dialogModel ->
val params = mutableMapOf<String, Any?>("haWbList" to listOf(bean))
if (dialogModel.resetStatusCode != null) {
params["restStatus"] = dialogModel.resetStatusCode
}
launchLoadingCollect({ NetApply.api.resetArriveDeclare(params.toRequestBody()) }) {
onSuccess = {
showToast("状态重置成功,请返回列表页下拉刷新查看最新状态")
viewModelScope.launch {
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).emit("refresh")
}
}
}
}
dialog.show()
}
/**
* 底部「申报」:批量申报当前选中的分单。
*/
fun declareClick() {
val selected = displayList.value?.filter { it.isSelected } ?: emptyList()
if (selected.isEmpty()) {
showToast("请选择要申报的分单")
return
}
val params = mapOf("haWbList" to selected).toRequestBody()
launchLoadingCollect({ NetApply.api.arriveDeclare(params) }) {
onSuccess = {
showToast("运抵申报成功")
viewModelScope.launch {
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).emit("refresh")
}
getTopActivity().finish()
}
}
}
companion object {
const val KEY_WB_NO = "wbNo"
}
}

View File

@@ -0,0 +1,119 @@
package com.lukouguoji.gjc.viewModel
import android.content.Intent
import androidx.lifecycle.MutableLiveData
import com.lukouguoji.module_base.base.BaseViewModel
import com.lukouguoji.module_base.bean.GjcHaWb
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.http.net.NetApply
import com.lukouguoji.module_base.ktx.launchCollect
import com.lukouguoji.module_base.ktx.launchLoadingCollect
import com.lukouguoji.module_base.ktx.showToast
import com.lukouguoji.module_base.ktx.toRequestBody
import com.lukouguoji.module_base.ktx.verifyNullOrEmpty
import dev.utils.app.info.KeyValue
/**
* 国际出港运抵-补充信息 ViewModel5.5寸手机版专属新页)
*
* 参照 Pad 端国际进港 [com.lukouguoji.gjj.viewModel.IntArrSupplementInfoViewModel] 的
* 「单一表单批量复制到选中列表」模式:对该运单的整个 haWbList 批量应用同一份收发货人信息。
*
* ⚠️ 后端暂无保存接口,见 [com.lukouguoji.module_base.http.net.Api.supplementArriveHaWb] 注释
* 与 documents/后端接口对接问题清单.xlsx。
*/
class IntExpArriveSupplementViewModel : BaseViewModel() {
// 表单编辑用数据对象(取首个分单填充,让用户看到已有数据)
val dataBean = MutableLiveData(GjcHaWb())
// 批量应用的目标分单列表
private var haWbList: List<GjcHaWb> = emptyList()
// 国家代码下拉列表
val countryCodeList = MutableLiveData<List<KeyValue>>(emptyList())
// 通讯方式下拉列表
val comTypeList = MutableLiveData<List<KeyValue>>(emptyList())
@Suppress("UNCHECKED_CAST")
fun initOnCreated(intent: Intent) {
val list = intent.getSerializableExtra(Constant.Key.DATA) as? ArrayList<GjcHaWb>
// .copy() 补上被 Java 序列化跳过的 @Transient 字段checked 等),见分单明细页同款注释
haWbList = (list ?: emptyList()).map { it.copy() }
dataBean.value = haWbList.firstOrNull()?.copy() ?: GjcHaWb()
loadCountryCodeList()
loadComTypeList()
}
private fun loadCountryCodeList() {
launchCollect({ NetApply.api.getCountryCodeList() }) {
onSuccess = { result ->
countryCodeList.value = result.data?.mapNotNull { bean ->
if (bean.code != null && bean.name != null) KeyValue(bean.name, bean.code) else null
} ?: emptyList()
}
}
}
private fun loadComTypeList() {
launchCollect({ NetApply.api.getCommunicateTypeList() }) {
onSuccess = { result ->
comTypeList.value = result.data?.mapNotNull { bean ->
if (bean.code != null && bean.name != null) KeyValue(bean.name, bean.code) else null
} ?: emptyList()
}
}
}
fun cancel() {
getTopActivity().finish()
}
/**
* 保存按钮点击 - 将表单信息复制到该运单的所有分单,批量提交。
*/
fun save() {
val formBean = dataBean.value ?: return
if (formBean.consigneeName.verifyNullOrEmpty("收货人名称不能为空")) return
if (formBean.consigneeCountryCode.verifyNullOrEmpty("收货人国家代码不能为空")) return
if (formBean.consigneeComType.verifyNullOrEmpty("收货人通讯方式不能为空")) return
if (formBean.consigneePnum.verifyNullOrEmpty("收货人联系号码不能为空")) return
if (formBean.consignorName.verifyNullOrEmpty("发货人名称不能为空")) return
if (formBean.consignorCountryCode.verifyNullOrEmpty("发货人国家代码不能为空")) return
if (formBean.consignorComType.verifyNullOrEmpty("发货人通讯方式不能为空")) return
if (formBean.consignorPnum.verifyNullOrEmpty("发货人联系号码不能为空")) return
if (haWbList.isEmpty()) {
showToast("无可保存的分单数据")
return
}
val updatedList = haWbList.map { haWb ->
haWb.copy(
consigneeName = formBean.consigneeName,
consigneeCountryCode = formBean.consigneeCountryCode,
consigneeComType = formBean.consigneeComType,
consigneePnum = formBean.consigneePnum,
consigneeAddress = formBean.consigneeAddress,
consignorName = formBean.consignorName,
consignorCountryCode = formBean.consignorCountryCode,
consignorComType = formBean.consignorComType,
consignorPnum = formBean.consignorPnum,
consignorAddress = formBean.consignorAddress
)
}
launchLoadingCollect({ NetApply.api.supplementArriveHaWb(updatedList.toRequestBody()) }) {
onSuccess = {
showToast("保存成功")
getTopActivity().finish()
}
onFailed = { code, msg ->
showToast("保存失败:$msg(后端接口暂未支持,见接口问题清单)")
}
}
}
}

View File

@@ -20,6 +20,7 @@ import com.lukouguoji.module_base.ktx.launchLoadingCollect
import com.lukouguoji.module_base.ktx.showToast import com.lukouguoji.module_base.ktx.showToast
import com.lukouguoji.module_base.ktx.toRequestBody import com.lukouguoji.module_base.ktx.toRequestBody
import com.lukouguoji.module_base.model.ScanModel import com.lukouguoji.module_base.model.ScanModel
import dev.utils.app.info.KeyValue
import dev.utils.common.DateUtils import dev.utils.common.DateUtils
import com.lukouguoji.module_base.ktx.formatDate import com.lukouguoji.module_base.ktx.formatDate
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -45,6 +46,7 @@ class IntExpArriveViewModel : BasePageViewModel() {
fun onItemCheckChanged() { fun onItemCheckChanged() {
updateCheckAllStatus() updateCheckAllStatus()
updateCheckAllStatusPhone()
} }
fun updateCheckAllStatus() { fun updateCheckAllStatus() {
@@ -52,6 +54,101 @@ class IntExpArriveViewModel : BasePageViewModel() {
isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() } isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() }
} }
// ========== 5.5寸手机版专属(平板布局不引用,零影响) ==========
/** 当前 Tab"pending"(待运抵) / "shipped"(已运抵)。接口无申报状态查询参数Tab 由客户端对已加载数据拆分 */
val currentTab = MutableLiveData("pending")
/** Tab 配置 */
val arriveTabs = MutableLiveData(
listOf(KeyValue("待运抵", "pending"), KeyValue("已运抵", "shipped"))
)
/** 两个 Tab 的角标计数(当前已加载数据的客户端统计,非全量,见接口问题清单) */
val arriveTabCounts = MutableLiveData(listOf("", ""))
/** 手机版全选状态(仅统计待运抵 Tab 内的项,与 Pad 端 [isAllChecked] 统计口径不同) */
val isAllCheckedPhone = MutableLiveData(false)
/** 手机版已选数量(底部操作条「已选 N 项」) */
val selectedCountPhone = MutableLiveData("0")
/** 手机版筛选弹层「代理」(后端 pageQuery 支持 agentCode 入参,复用既有 agentCode 语义查询) */
val agentCodePhone = MutableLiveData("")
val agentListPhone = MutableLiveData<List<KeyValue>>(emptyList())
private var phoneExtrasEnabled = false
/**
* 完整已加载列表(跨分页累计,未按 Tab 过滤)。
*
* ⚠️ RecyclerView/LinearLayoutManager 不会像普通 ViewGroup 那样让 `View.GONE` 的子项
* 自动塌陷为 0 高度——它仍按子项的测量高度参与滚动区域计算,导致"隐藏"的卡片在列表里
* 留下一段空白(已实机截图验证)。因此 Tab 切换不能靠给 item 加 visibility 绑定,
* 必须真正地把适配器的数据集替换成过滤后的子集([applyTabFilterPhone])。
*/
private var allLoadedList: List<GjcMaWb> = emptyList()
/**
* 开启手机版专属数据:加载「代理」筛选下拉。仅由手机形态的 Activity 调用。
*/
fun initPhoneExtras() {
phoneExtrasEnabled = true
launchCollect({ NetApply.api.getIntExpAgentList() }) {
onSuccess = { result ->
agentListPhone.postValue(
listOf(KeyValue("全部", "")) + (result.data ?: emptyList()).map { KeyValue(it.name ?: "", it.code ?: "") }
)
}
}
}
/**
* 手机版 Tab 切换:将适配器数据集替换为过滤后的子集(不重新请求)。
* 由 Activity 在 [com.lukouguoji.module_base.ui.weight.phone.PhoneStatusTab] 的
* 双向绑定写入 currentTab 后调用。
*/
fun onTabChangedPhone() {
applyTabFilterPhone()
}
private fun applyTabFilterPhone() {
val isPendingTab = currentTab.value == "pending"
val filtered = allLoadedList.filter { it.isPending == isPendingTab }
pageModel.rv?.commonAdapter()?.refresh(filtered)
updateCheckAllStatusPhone()
}
/**
* 根据完整已加载列表重新计算 Tab 角标计数(每次数据变化后调用)。
*/
private fun updatePhoneTabCounts() {
val pending = allLoadedList.count { it.isPending }.toString()
val shipped = allLoadedList.count { !it.isPending }.toString()
arriveTabCounts.value = listOf(pending, shipped)
}
/**
* 手机版全选(适配器此时已只包含当前 Tab 的子集,待运抵 Tab 下即为全部可选项)。
*/
fun checkAllClickPhone() {
val list = pageModel.rv?.commonAdapter()?.items as? List<GjcMaWb> ?: return
val shouldCheckAll = !isAllCheckedPhone.value!!
list.forEach { it.checked.set(shouldCheckAll) }
isAllCheckedPhone.value = shouldCheckAll
updateCheckAllStatusPhone()
pageModel.rv?.commonAdapter()?.notifyDataSetChanged()
}
/**
* 更新手机版全选状态与已选计数(基于适配器当前子集,即当前 Tab 的数据)。
*/
fun updateCheckAllStatusPhone() {
val list = pageModel.rv?.commonAdapter()?.items as? List<GjcMaWb> ?: return
isAllCheckedPhone.value = list.isNotEmpty() && list.all { it.checked.get() }
selectedCountPhone.value = list.count { it.checked.get() }.toString()
}
// ========== 全局展开状态 ========== // ========== 全局展开状态 ==========
/** /**
* 全局展开状态 * 全局展开状态
@@ -292,18 +389,53 @@ class IntExpArriveViewModel : BasePageViewModel() {
} }
} }
/**
* 手机版:卡片长按菜单「重置」(单条,已运抵 Tab 专用,对应设计稿长按浮层)。
*/
fun resetSingleDeclareClick(bean: GjcMaWb) {
bean.actionMenuVisible.set(false)
val dialog = IntExpArriveResetDialogModel { dialogModel ->
val params = mutableMapOf<String, Any?>("maWbList" to listOf(bean))
if (dialogModel.resetStatusCode != null) {
params["restStatus"] = dialogModel.resetStatusCode
}
launchLoadingCollect({ NetApply.api.resetArriveDeclare(params.toRequestBody()) }) {
onSuccess = {
showToast("状态重置成功")
viewModelScope.launch {
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).emit("refresh")
}
refresh()
}
}
}
dialog.show()
}
/** /**
* 获取数据 (重写BasePageViewModel) * 获取数据 (重写BasePageViewModel)
*/ */
override fun getData() { override fun getData() {
// 构建搜索条件 // 构建搜索条件
val filterParams = mapOf( val filterParams = mutableMapOf<String, Any?>(
"fdate" to flightDate.value?.ifEmpty { null }, "fdate" to flightDate.value?.ifEmpty { null },
"fno" to flightNo.value?.ifEmpty { null }, "fno" to flightNo.value?.ifEmpty { null },
"wbNo" to waybillNo.value?.ifEmpty { null }, "wbNo" to waybillNo.value?.ifEmpty { null },
"hno" to hno.value?.ifEmpty { null } "hno" to hno.value?.ifEmpty { null }
) )
// 手机版专属条件(平板 phoneExtrasEnabled 恒为 false请求体与改造前完全一致
if (phoneExtrasEnabled) {
// 搜索分流与出港计重页一致11 位数字精确匹配 wbNo其余走 likeNo 模糊
val key = waybillNo.value?.trim() ?: ""
if (key.isNotEmpty() && key.length != 11) {
filterParams["wbNo"] = null
filterParams["likeNo"] = key
}
filterParams["agentCode"] = agentCodePhone.value?.ifEmpty { null }
}
// 列表参数 (含分页) // 列表参数 (含分页)
val listParams = (filterParams + mapOf( val listParams = (filterParams + mapOf(
"pageNum" to pageModel.page, "pageNum" to pageModel.page,
@@ -315,8 +447,21 @@ class IntExpArriveViewModel : BasePageViewModel() {
// 获取列表 (带Loading) // 获取列表 (带Loading)
launchLoadingCollect({ NetApply.api.getIntExpArriveList(listParams) }) { launchLoadingCollect({ NetApply.api.getIntExpArriveList(listParams) }) {
onSuccess = { onSuccess = { result ->
pageModel.handleListBean(it) { updateCheckAllStatus() } // 手机版:自行维护完整累计列表(不依赖 adapter.items 的历史状态,见 allLoadedList 注释)
if (phoneExtrasEnabled) {
val newPageItems = result.list ?: emptyList()
allLoadedList = if (pageModel.page <= 1) newPageItems else allLoadedList + newPageItems
}
pageModel.handleListBean(result) {
updateCheckAllStatus()
if (phoneExtrasEnabled) {
// 用完整列表强制覆盖 adapter 数据集为当前 Tab 的过滤子集
applyTabFilterPhone()
updatePhoneTabCounts()
}
}
// 数据加载完成后,重置全局展开状态为收起 // 数据加载完成后,重置全局展开状态为收起
isAllExpanded.value = false isAllExpanded.value = false
} }

View File

@@ -0,0 +1,244 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.lukouguoji.module_base.ui.weight.search.layout.SearchLayoutType" />
<import type="com.lukouguoji.module_base.R" />
<variable
name="viewModel"
type="com.lukouguoji.gjc.viewModel.IntExpArriveViewModel" />
<!-- 平板端不使用仅为与手机变体layout/activity_int_exp_arrive.xml保持变量一致 -->
<variable
name="activity"
type="com.lukouguoji.gjc.activity.IntExpArriveActivity" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f2"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<!-- 搜索区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- 航班日期 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"请选择航班日期"}'
icon="@{@drawable/img_date}"
type="@{SearchLayoutType.DATE}"
value="@={viewModel.flightDate}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<!-- 航班号 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"请输入航班号"}'
type="@{SearchLayoutType.INPUT}"
value="@={viewModel.flightNo}"
setUpperCaseAlphanumeric="@{true}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<!-- 运单号 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"请输入运单号"}'
icon="@{@drawable/img_scan}"
setOnIconClickListener="@{(v)-> viewModel.scanWaybill()}"
type="@{SearchLayoutType.INPUT}"
value="@={viewModel.waybillNo}"
autoQueryEnabled="@{true}"
autoQueryUrl="@{`/IntExpArrive/queryWbNoList`}"
autoQueryParamKey="@{`wbNo`}"
autoQueryMinLength="@{4}"
autoQueryMaxLength="@{8}"
autoQueryTitle="@{`选择运单号`}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<!-- 分单号 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"请输入分单号"}'
icon="@{@drawable/img_scan}"
setOnIconClickListener="@{(v)-> viewModel.scanHaWb()}"
type="@{SearchLayoutType.INPUT}"
value="@={viewModel.hno}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<!-- 搜索按钮 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical|start"
android:orientation="horizontal"
android:paddingHorizontal="24dp">
<ImageView
android:layout_width="36dp"
android:layout_height="36dp"
android:onClick="@{()-> viewModel.searchClick()}"
android:padding="2dp"
android:src="@drawable/img_search" />
<!-- 全局展开/收起按钮 -->
<ImageView
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginStart="16dp"
android:onClick="@{()-> viewModel.toggleAllExpand()}"
android:padding="2dp"
android:scaleType="fitCenter"
loadImage="@{viewModel.isAllExpanded ? R.drawable.ic_new_expand_1 : R.drawable.ic_new_expand_1}"
android:contentDescription="展开/收起全部子列表" />
</LinearLayout>
</LinearLayout>
<!-- 列表 -->
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/srl"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="10dp"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="3"
tools:listitem="@layout/item_int_exp_arrive" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<!-- 底部统计和操作按钮 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@android:color/white"
android:gravity="center_vertical"
android:paddingHorizontal="15dp">
<!-- 全选按钮 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:gravity="center_vertical"
android:onClick="@{()-> viewModel.checkAllClick()}"
android:orientation="horizontal">
<ImageView
android:id="@+id/checkIcon"
setIVCheckAllImage="@{viewModel.isAllChecked}"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="5dp"
android:src="@drawable/img_check_all_unchecked" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="全选"
android:textColor="@color/color_66"
android:textSize="18sp" />
</LinearLayout>
<!-- 统计信息 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{"合计:"+viewModel.totalCount+"票"}'
android:textColor="@color/bottom_tool_tips_text_color"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text='@{"总件数:"+viewModel.totalPc}'
android:textColor="@color/bottom_tool_tips_text_color"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text='@{"总重量:"+viewModel.totalWeight}'
android:textColor="@color/bottom_tool_tips_text_color"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
<!-- 批量操作按钮组 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
style="@style/tv_bottom_btn"
android:layout_marginEnd="15dp"
android:onClick="@{()-> viewModel.resetDeclareClick()}"
android:text="状态重置" />
<TextView
style="@style/tv_bottom_btn"
android:layout_marginLeft="0dp"
android:layout_marginEnd="15dp"
android:onClick="@{()-> viewModel.deleteDeclareClick()}"
android:text="删除申报" />
<TextView
style="@style/tv_bottom_btn"
android:layout_marginLeft="0dp"
android:background="@drawable/bg_red_btn_bottom"
android:onClick="@{()-> viewModel.arriveReportClick()}"
android:text="运抵申报" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</layout>

View File

@@ -0,0 +1,520 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<variable
name="bean"
type="com.lukouguoji.module_base.bean.GjcMaWb" />
<variable
name="position"
type="Integer" />
<!-- 以下两个变量平板端不使用仅为与手机变体layout/item_int_exp_arrive.xml保持变量一致 -->
<variable
name="activity"
type="com.lukouguoji.gjc.activity.IntExpArriveActivity" />
<variable
name="viewModel"
type="com.lukouguoji.gjc.viewModel.IntExpArriveViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="10dp"
android:orientation="vertical">
<!-- 白色卡片 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_white_radius_8"
android:orientation="vertical">
<!-- 主要内容区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingVertical="20dp"
android:paddingHorizontal="10dp">
<!-- 选中图标 (飞机图标,根据选择状态切换图片) -->
<ImageView
android:id="@+id/iv_icon"
loadImage="@{bean.checked.get() ? @drawable/img_plane_s : @drawable/img_plane}"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="0.5px"
android:layout_gravity="center"
android:src="@drawable/img_plane" />
<!-- 运单信息区域 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_weight="0.8"
android:orientation="vertical">
<!-- 第一行:运单号、状态、代理、件数、重量 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- 运单号 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单号:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.wbNo}"
android:textColor="@color/colorPrimary"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
<!-- 状态 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="状态:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@{`01`.equals(bean.declareStatus) ? @drawable/tag_status_green : (`W`.equals(bean.declareStatus) ? @drawable/tag_status_blue : @drawable/tag_status_gray)}"
android:paddingHorizontal="8dp"
android:paddingVertical="2dp"
android:text="@{bean.declareStatus}"
android:textColor="@{`01`.equals(bean.declareStatus) ? @color/text_green : (`W`.equals(bean.declareStatus) ? @color/colorPrimary : @color/text_gray)}"
android:textSize="14sp"
android:visibility="@{bean.declareStatus != null &amp;&amp; !bean.declareStatus.isEmpty() ? View.VISIBLE : View.GONE}" />
</LinearLayout>
<!-- 代理 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="代理:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:text="@{bean.agentName}"
android:textColor="@color/text_normal"
android:textSize="15sp" />
</LinearLayout>
<!-- 件数 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="件数:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(bean.pc)}"
android:textColor="@color/text_normal"
android:textSize="15sp" />
</LinearLayout>
<!-- 重量 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="重量:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf((int)bean.weight)}"
android:textColor="@color/text_normal"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
<!-- 第二行:航程、计重状态、运抵状态、运单类型、分单数 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- 航程 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="航程:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.range}"
android:textColor="@color/text_normal"
android:textSize="15sp" />
</LinearLayout>
<!-- 计重状态 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="计重状态:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@{`1`.equals(bean.checkIn) ? @drawable/tag_status_green : (`2`.equals(bean.checkIn) ? @drawable/tag_status_blue : @drawable/tag_status_gray)}"
android:paddingHorizontal="8dp"
android:paddingVertical="2dp"
android:text="@{bean.checkInText}"
android:textColor="@{`1`.equals(bean.checkIn) ? @color/text_green : (`2`.equals(bean.checkIn) ? @color/colorPrimary : @color/text_gray)}"
android:textSize="14sp"
android:visibility="@{bean.checkIn != null &amp;&amp; !bean.checkIn.isEmpty() ? View.VISIBLE : View.GONE}" />
</LinearLayout>
<!-- 运抵状态 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运抵状态:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@{`0`.equals(bean.arriveFlag) ? @drawable/tag_status_green : (`1`.equals(bean.arriveFlag) ? @drawable/tag_status_orange : @drawable/tag_status_gray)}"
android:paddingHorizontal="8dp"
android:paddingVertical="2dp"
android:text="@{bean.arriveFlagText}"
android:textColor="@{`0`.equals(bean.arriveFlag) ? @color/text_green : (`1`.equals(bean.arriveFlag) ? @color/text_orange : @color/text_gray)}"
android:textSize="14sp"
android:visibility="@{bean.arriveFlag != null &amp;&amp; !bean.arriveFlag.isEmpty() ? View.VISIBLE : View.GONE}" />
</LinearLayout>
<!-- 运单类型 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单类型:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.awbName}"
android:textColor="@color/text_normal"
android:textSize="15sp" />
</LinearLayout>
<!-- 分单数 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分单数:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(bean.haWbNumber)}"
android:textColor="@color/text_normal"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<!-- 展开按钮 -->
<ImageView
android:id="@+id/iv_show"
android:layout_width="match_parent"
android:layout_height="20dp"
android:paddingVertical="2.5dp"
android:layout_marginTop="-20dp"
android:scaleType="center"
android:src="@mipmap/img_down" />
</LinearLayout>
<!-- 子订单列表容器(白色圆角卡片,圆角同主单) -->
<LinearLayout
visible="@{bean.showMore}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@drawable/bg_white_radius_8"
android:orientation="vertical"
android:visibility="gone">
<!-- 暂无数据提示 -->
<TextView
android:id="@+id/tv_empty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingVertical="15dp"
android:text="暂无分单数据"
android:textColor="@color/text_gray"
android:textSize="14sp"
android:visibility="gone" />
<!-- 表头(浅蓝色背景,仅 Title 有背景色,顶部圆角同卡片) -->
<LinearLayout
android:id="@+id/ll_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_arrive_sub_header"
android:orientation="horizontal"
android:paddingHorizontal="10dp"
android:paddingVertical="10dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:gravity="center"
android:text="选项"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.2"
android:gravity="center"
android:text="分单号"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center"
android:text="件数"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center"
android:text="重量(KG)"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="申报状态"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="品名(中)"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.9"
android:gravity="center"
android:text="申报次数"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.9"
android:gravity="center"
android:text="申报费率"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.9"
android:gravity="center"
android:text="删除次数"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.9"
android:gravity="center"
android:text="删除费率"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
android:id="@+id/divider_header"
android:layout_width="match_parent"
android:layout_height="1px"
app:dividerColor="@color/sub_list_divider" />
<!-- 子列表 RecyclerView -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_sub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>
</LinearLayout>
</layout>

View File

@@ -1,239 +1,161 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--
国际出港运抵 —— 手机版布局5.5 寸手持端,最小宽度 < 600dp 时生效)
平板版为同名文件 layout-sw600dp/activity_int_exp_arrive.xml两者是同一布局的资源变体
DataBinding 因此生成同一个 ActivityIntExpArriveBinding 类。
变体之间必须满足:
· DataBinding 变量完全一致viewModel / activity
· 保留 Activity 中引用的控件 idsrl / rv
→ IntExpArriveViewModel 的业务逻辑与接口调用全部复用,平板端行为不受影响
交互差异(均复用既有 ViewModel 字段与接口,或为纯客户端拆分,零新增请求):
· 平板 4 个横排搜索条 → 手机顶部搜索框(运单号)+ 底部筛选弹层(航班日期/航班号/代理)
· 新增「待运抵 / 已运抵」Tab客户端按 declareStatus 是否为空拆分,接口无此查询参数)
· 平板内嵌分单展开列表 → 手机「查看分单」按钮进入独立「分单明细」页
· 平板常驻底部全选+状态重置+删除申报+运抵申报 → 手机仅待运抵 Tab 显示全选+申报;
状态重置/回执改为卡片长按浮层(已运抵 Tab删除申报设计稿未提供手机端不可用
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android" <layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<data> <data>
<import type="com.lukouguoji.module_base.ui.weight.search.layout.SearchLayoutType" /> <import type="android.view.View" />
<import type="com.lukouguoji.module_base.R" />
<variable <variable
name="viewModel" name="viewModel"
type="com.lukouguoji.gjc.viewModel.IntExpArriveViewModel" /> type="com.lukouguoji.gjc.viewModel.IntExpArriveViewModel" />
<variable
name="activity"
type="com.lukouguoji.gjc.activity.IntExpArriveActivity" />
</data> </data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/phone_page_bg">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/color_f2"
android:orientation="vertical"> android:orientation="vertical">
<include layout="@layout/title_tool_bar" /> <include layout="@layout/title_tool_bar" />
<!-- 搜索区域 --> <!-- ==================== 搜索行 ==================== -->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp" android:background="@color/white"
android:layout_marginTop="10dp" android:orientation="vertical"
android:gravity="center_vertical" android:paddingHorizontal="16dp"
android:orientation="horizontal"> android:paddingTop="16dp"
android:paddingBottom="12dp">
<!-- 航班日期 --> <com.lukouguoji.module_base.ui.weight.phone.PhoneSearchBar
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout android:layout_width="match_parent"
hint='@{"请选择航班日期"}'
icon="@{@drawable/img_date}"
type="@{SearchLayoutType.DATE}"
value="@={viewModel.flightDate}"
android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" /> hint='@{"搜索运单号"}'
setOnFilterClickListener="@{(v)-> activity.toggleFilterPanel()}"
<!-- 航班号 --> setOnScanClickListener="@{(v)-> viewModel.scanWaybill()}"
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout setRefreshCallBack="@{viewModel::searchClick}"
hint='@{"请输入航班号"}' upperCase="@{true}"
type="@{SearchLayoutType.INPUT}" value="@={viewModel.waybillNo}" />
value="@={viewModel.flightNo}"
setUpperCaseAlphanumeric="@{true}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<!-- 运单号 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"请输入运单号"}'
icon="@{@drawable/img_scan}"
setOnIconClickListener="@{(v)-> viewModel.scanWaybill()}"
type="@{SearchLayoutType.INPUT}"
value="@={viewModel.waybillNo}"
autoQueryEnabled="@{true}"
autoQueryUrl="@{`/IntExpArrive/queryWbNoList`}"
autoQueryParamKey="@{`wbNo`}"
autoQueryMinLength="@{4}"
autoQueryMaxLength="@{8}"
autoQueryTitle="@{`选择运单号`}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<!-- 分单号 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"请输入分单号"}'
icon="@{@drawable/img_scan}"
setOnIconClickListener="@{(v)-> viewModel.scanHaWb()}"
type="@{SearchLayoutType.INPUT}"
value="@={viewModel.hno}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<!-- 搜索按钮 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical|start"
android:orientation="horizontal"
android:paddingHorizontal="24dp">
<ImageView
android:layout_width="36dp"
android:layout_height="36dp"
android:onClick="@{()-> viewModel.searchClick()}"
android:padding="2dp"
android:src="@drawable/img_search" />
<!-- 全局展开/收起按钮 -->
<ImageView
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginStart="16dp"
android:onClick="@{()-> viewModel.toggleAllExpand()}"
android:padding="2dp"
android:scaleType="fitCenter"
loadImage="@{viewModel.isAllExpanded ? R.drawable.ic_new_expand_1 : R.drawable.ic_new_expand_1}"
android:contentDescription="展开/收起全部子列表" />
</LinearLayout> </LinearLayout>
</LinearLayout> <!-- ==================== 待运抵 / 已运抵 Tab ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneStatusTab
android:layout_width="match_parent"
android:layout_height="wrap_content"
counts="@{viewModel.arriveTabCounts}"
setOnTabChanged="@{()-> activity.onArriveTabChanged()}"
tabs="@{viewModel.arriveTabs}"
value="@={viewModel.currentTab}" />
<!-- 列表 --> <View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/phone_divider" />
<!-- ==================== 列表 ==================== -->
<com.scwang.smart.refresh.layout.SmartRefreshLayout <com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/srl" android:id="@+id/srl"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="10dp"
android:layout_weight="1"> android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv" android:id="@+id/rv"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clipToPadding="false"
android:overScrollMode="never" android:overScrollMode="never"
android:paddingTop="4dp"
android:paddingBottom="12dp"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="3" tools:itemCount="2"
tools:listitem="@layout/item_int_exp_arrive" /> tools:listitem="@layout/item_int_exp_arrive" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout> </com.scwang.smart.refresh.layout.SmartRefreshLayout>
<!-- 底部统计和操作按钮 --> <!-- ==================== 底部操作条(仅待运抵 Tab 显示) ==================== -->
<LinearLayout <com.lukouguoji.module_base.ui.weight.phone.PhoneBottomBar
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@android:color/white"
android:gravity="center_vertical"
android:paddingHorizontal="15dp">
<!-- 全选按钮 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="5dp" actionText='@{"申报"}'
android:gravity="center_vertical" allChecked="@{viewModel.isAllCheckedPhone}"
android:onClick="@{()-> viewModel.checkAllClick()}" countText='@{"已选 " + viewModel.selectedCountPhone + " 项"}'
android:orientation="horizontal"> android:visibility="@{`pending`.equals(viewModel.currentTab) ? View.VISIBLE : View.GONE}"
setOnActionClick="@{(v)-> viewModel.arriveReportClick()}"
<ImageView setOnAllCheckClick="@{(v)-> viewModel.checkAllClickPhone()}" />
android:id="@+id/checkIcon"
setIVCheckAllImage="@{viewModel.isAllChecked}"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="5dp"
android:src="@drawable/img_check_all_unchecked" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="全选"
android:textColor="@color/color_66"
android:textSize="18sp" />
</LinearLayout> </LinearLayout>
<!-- 统计信息 --> <!-- ==================== 筛选弹层 ==================== -->
<LinearLayout <com.lukouguoji.module_base.ui.weight.phone.PhoneFilterPanel
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="8dp"
panelVisible="@{activity.filterPanelVisible}"
setOnConfirmClick="@{(v)-> activity.confirmFilter()}"
setOnDismissClick="@{(v)-> activity.toggleFilterPanel()}"
setOnResetClick="@{(v)-> activity.resetFilter()}"
title='@{"筛选条件"}'>
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="20dp" hint='@{"请选择航班日期"}'
android:layout_weight="1" title='@{"航班日期"}'
android:gravity="center_vertical" type="@{com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayoutType.DATE}"
android:orientation="horizontal"> value="@={viewModel.flightDate}" />
<TextView <com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text='@{"合计:"+viewModel.totalCount+"票"}' hint='@{"请输入航班号"}'
android:textColor="@color/bottom_tool_tips_text_color" title='@{"航班号"}'
android:textSize="18sp" type="@{com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayoutType.INPUT}"
android:textStyle="bold" /> value="@={viewModel.flightNo}" />
<TextView <com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="20dp" hint='@{"请选择代理"}'
android:text='@{"总件数:"+viewModel.totalPc}' list="@{viewModel.agentListPhone}"
android:textColor="@color/bottom_tool_tips_text_color" title='@{"代理"}'
android:textSize="18sp" type="@{com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayoutType.SPINNER}"
android:textStyle="bold" /> value="@={viewModel.agentCodePhone}" />
<TextView </com.lukouguoji.module_base.ui.weight.phone.PhoneFilterPanel>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text='@{"总重量:"+viewModel.totalWeight}'
android:textColor="@color/bottom_tool_tips_text_color"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout> </FrameLayout>
<!-- 批量操作按钮组 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
style="@style/tv_bottom_btn"
android:layout_marginEnd="15dp"
android:onClick="@{()-> viewModel.resetDeclareClick()}"
android:text="状态重置" />
<TextView
style="@style/tv_bottom_btn"
android:layout_marginLeft="0dp"
android:layout_marginEnd="15dp"
android:onClick="@{()-> viewModel.deleteDeclareClick()}"
android:text="删除申报" />
<TextView
style="@style/tv_bottom_btn"
android:layout_marginLeft="0dp"
android:background="@drawable/bg_red_btn_bottom"
android:onClick="@{()-> viewModel.arriveReportClick()}"
android:text="运抵申报" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</layout> </layout>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
国际出港运抵-回执内容 —— 5.5 寸手机版专属只读新页(平板端无对应页面)
数据来自主列表页已加载的 GjcMaWb.haWbList[].response / arrivalOpDate零新增请求。
对应设计稿 documents/5.5寸手持端设计文件/04_出港运抵/receipt.html。
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.lukouguoji.gjc.viewModel.IntExpArriveReceiptViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/phone_page_bg"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:clipToPadding="false"
android:overScrollMode="never"
android:paddingTop="12dp"
android:paddingBottom="16dp"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="3"
tools:listitem="@layout/item_int_exp_arrive_receipt" />
</LinearLayout>
</layout>

View File

@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
国际出港运抵-分单明细 —— 5.5 寸手机版专属新页(平板端无对应页面,分单在平板上内嵌展开于主列表)
数据来自主列表页已加载的 GjcMaWb.haWbListIntent 传入),不发起任何新增网络请求。
对应设计稿 documents/5.5寸手持端设计文件/04_出港运抵/suborder.html。
与设计稿的差异:
· 筛选弹层设计稿含"航班日期/航班号/代理"三项,但本页数据是单个运单的分单集合,
这三项在集合内恒为同一值,筛选无实际意义(判断为设计稿沿用主列表筛选组件模板未定制),
故只保留真正可筛选的「分单号」
· 搜索框设计稿占位符字面是"搜索运单号"(同样的模板复用),本页按实际语义改为"搜索分单号"
并去掉扫码图标(此场景无可扫描目标)
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.lukouguoji.gjc.viewModel.IntExpArriveSubOrderViewModel" />
<variable
name="activity"
type="com.lukouguoji.gjc.activity.IntExpArriveSubOrderActivity" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/phone_page_bg">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<!-- ==================== 搜索行 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingTop="16dp"
android:paddingBottom="12dp">
<com.lukouguoji.module_base.ui.weight.phone.PhoneSearchBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"搜索分单号"}'
setOnFilterClickListener="@{(v)-> activity.toggleFilterPanel()}"
setRefreshCallBack="@{viewModel::searchClick}"
showScan="@{false}"
value="@={viewModel.hnoFilter}" />
</LinearLayout>
<!-- ==================== 列表 ==================== -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:clipToPadding="false"
android:overScrollMode="never"
android:paddingTop="4dp"
android:paddingBottom="12dp"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="3"
tools:listitem="@layout/item_int_exp_arrive_sub_order" />
<!-- ==================== 底部操作条 ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneBottomBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
actionText='@{"申报"}'
allChecked="@{viewModel.isAllChecked}"
countText='@{"已选 " + viewModel.selectedCount + " 项"}'
setOnActionClick="@{(v)-> viewModel.declareClick()}"
setOnAllCheckClick="@{(v)-> activity.checkAllClick()}" />
</LinearLayout>
<!-- ==================== 筛选弹层 ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFilterPanel
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="8dp"
panelVisible="@{activity.filterPanelVisible}"
setOnConfirmClick="@{(v)-> activity.confirmFilter()}"
setOnDismissClick="@{(v)-> activity.toggleFilterPanel()}"
setOnResetClick="@{(v)-> activity.resetFilter()}"
title='@{"筛选条件"}'>
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请输入分单号"}'
title='@{"分单号"}'
type="@{com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayoutType.INPUT}"
value="@={viewModel.hnoFilter}" />
</com.lukouguoji.module_base.ui.weight.phone.PhoneFilterPanel>
</FrameLayout>
</layout>

View File

@@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
国际出港运抵-补充信息 —— 5.5 寸手机版专属新页(平板端无对应页面)
参照 Pad 端国际进港「收发货人信息」补充页IntArrSupplementInfoActivity的批量应用模式
对该运单整个 haWbList 批量应用同一份表单。后端暂无保存接口,见 ViewModel 顶部注释与
documents/后端接口对接问题清单.xlsx。对应设计稿 04_出港运抵/supplement.html。
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.lukouguoji.module_base.ui.weight.phone.PhoneFormRowType" />
<variable
name="viewModel"
type="com.lukouguoji.gjc.viewModel.IntExpArriveSupplementViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/phone_page_bg"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- 收货人信息 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card"
android:orientation="vertical"
android:padding="14dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<View
android:layout_width="4dp"
android:layout_height="16dp"
android:background="@color/phone_primary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="收货人信息"
android:textColor="@color/phone_text_strong"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
hint='@{"请输入收货人名称"}'
required="@{true}"
title='@{"收货人名称"}'
type="@{PhoneFormRowType.INPUT}"
value="@={viewModel.dataBean.consigneeName}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择国家代码"}'
list="@{viewModel.countryCodeList}"
required="@{true}"
title='@{"国家代码"}'
type="@{PhoneFormRowType.SELECT}"
value="@={viewModel.dataBean.consigneeCountryCode}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择"}'
list="@{viewModel.comTypeList}"
required="@{true}"
title='@{"通讯方式"}'
type="@{PhoneFormRowType.SELECT}"
value="@={viewModel.dataBean.consigneeComType}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请输入联系号码"}'
required="@{true}"
title='@{"联系号码"}'
type="@{PhoneFormRowType.INPUT}"
value="@={viewModel.dataBean.consigneePnum}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请输入地址"}'
title='@{"地址"}'
type="@{PhoneFormRowType.INPUT}"
value="@={viewModel.dataBean.consigneeAddress}" />
</LinearLayout>
<!-- 发货人信息 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:background="@drawable/bg_phone_card"
android:orientation="vertical"
android:padding="14dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<View
android:layout_width="4dp"
android:layout_height="16dp"
android:background="@color/phone_primary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="发货人信息"
android:textColor="@color/phone_text_strong"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
hint='@{"请输入发货人名称"}'
required="@{true}"
title='@{"发货人名称"}'
type="@{PhoneFormRowType.INPUT}"
value="@={viewModel.dataBean.consignorName}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择国家代码"}'
list="@{viewModel.countryCodeList}"
required="@{true}"
title='@{"国家代码"}'
type="@{PhoneFormRowType.SELECT}"
value="@={viewModel.dataBean.consignorCountryCode}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择"}'
list="@{viewModel.comTypeList}"
required="@{true}"
title='@{"通讯方式"}'
type="@{PhoneFormRowType.SELECT}"
value="@={viewModel.dataBean.consignorComType}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请输入联系号码"}'
required="@{true}"
title='@{"联系号码"}'
type="@{PhoneFormRowType.INPUT}"
value="@={viewModel.dataBean.consignorPnum}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请输入地址"}'
title='@{"地址"}'
type="@{PhoneFormRowType.INPUT}"
value="@={viewModel.dataBean.consignorAddress}" />
</LinearLayout>
</LinearLayout>
</ScrollView>
<!-- 确定 -->
<TextView
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_margin="16dp"
android:background="@drawable/bg_phone_btn_primary"
android:gravity="center"
android:onClick="@{()-> viewModel.save()}"
android:text="确定"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</layout>

View File

@@ -1,6 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--
国际出港运抵 - 列表卡片(手机版变体)
平板版为 layout-sw600dp/item_int_exp_arrive.xml横排 KV + 内嵌分单展开列表)。
变量 bean / position 与平板一致;根节点保留 id ll不使用仅保持结构一致
手机独有radio 选择圈仅待运抵可选、长按操作浮层activity/viewModel 新增变量,
平板变体已同步补充但不使用)。
卡片形态按 Tab 区分(由 Activity 长按/点击驱动,视觉上两种形态共用同一布局,
仅申报状态标签、提前运抵标签、选择圈的显隐不同):
· 待运抵:显示选择圈 + 红色「提前运抵」标签arriveFlag=1 时);长按仅「补充」
· 已运抵显示申报状态三色标签01绿/W靛蓝/其余琥珀);长按「重置」+「回执」
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android" <layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:tools="http://schemas.android.com/tools">
<data> <data>
@@ -13,499 +26,241 @@
<variable <variable
name="position" name="position"
type="Integer" /> type="Integer" />
<variable
name="activity"
type="com.lukouguoji.gjc.activity.IntExpArriveActivity" />
<variable
name="viewModel"
type="com.lukouguoji.gjc.viewModel.IntExpArriveViewModel" />
</data> </data>
<LinearLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp" android:layout_marginHorizontal="16dp"
android:layout_marginTop="10dp" android:layout_marginTop="10dp">
android:orientation="vertical">
<!-- 白色卡片 --> <androidx.appcompat.widget.LinearLayoutCompat
<LinearLayout android:id="@+id/ll"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/bg_white_radius_8" android:background="@drawable/bg_phone_card"
android:orientation="vertical"> android:onLongClick="@{()-> activity.showCardActionPhone(bean)}"
<!-- 主要内容区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingVertical="20dp"
android:paddingHorizontal="10dp">
<!-- 选中图标 (飞机图标,根据选择状态切换图片) -->
<ImageView
android:id="@+id/iv_icon"
loadImage="@{bean.checked.get() ? @drawable/img_plane_s : @drawable/img_plane}"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="0.5px"
android:layout_gravity="center"
android:src="@drawable/img_plane" />
<!-- 运单信息区域 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_weight="0.8"
android:orientation="vertical">
<!-- 第一行:运单号、状态、代理、件数、重量 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- 运单号 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单号:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.wbNo}"
android:textColor="@color/colorPrimary"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
<!-- 状态 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="状态:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@{`01`.equals(bean.declareStatus) ? @drawable/tag_status_green : (`W`.equals(bean.declareStatus) ? @drawable/tag_status_blue : @drawable/tag_status_gray)}"
android:paddingHorizontal="8dp"
android:paddingVertical="2dp"
android:text="@{bean.declareStatus}"
android:textColor="@{`01`.equals(bean.declareStatus) ? @color/text_green : (`W`.equals(bean.declareStatus) ? @color/colorPrimary : @color/text_gray)}"
android:textSize="14sp"
android:visibility="@{bean.declareStatus != null &amp;&amp; !bean.declareStatus.isEmpty() ? View.VISIBLE : View.GONE}" />
</LinearLayout>
<!-- 代理 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="代理:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:text="@{bean.agentName}"
android:textColor="@color/text_normal"
android:textSize="15sp" />
</LinearLayout>
<!-- 件数 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="件数:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(bean.pc)}"
android:textColor="@color/text_normal"
android:textSize="15sp" />
</LinearLayout>
<!-- 重量 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="重量:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf((int)bean.weight)}"
android:textColor="@color/text_normal"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
<!-- 第二行:航程、计重状态、运抵状态、运单类型、分单数 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- 航程 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="航程:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.range}"
android:textColor="@color/text_normal"
android:textSize="15sp" />
</LinearLayout>
<!-- 计重状态 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="计重状态:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@{`1`.equals(bean.checkIn) ? @drawable/tag_status_green : (`2`.equals(bean.checkIn) ? @drawable/tag_status_blue : @drawable/tag_status_gray)}"
android:paddingHorizontal="8dp"
android:paddingVertical="2dp"
android:text="@{bean.checkInText}"
android:textColor="@{`1`.equals(bean.checkIn) ? @color/text_green : (`2`.equals(bean.checkIn) ? @color/colorPrimary : @color/text_gray)}"
android:textSize="14sp"
android:visibility="@{bean.checkIn != null &amp;&amp; !bean.checkIn.isEmpty() ? View.VISIBLE : View.GONE}" />
</LinearLayout>
<!-- 运抵状态 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运抵状态:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@{`0`.equals(bean.arriveFlag) ? @drawable/tag_status_green : (`1`.equals(bean.arriveFlag) ? @drawable/tag_status_orange : @drawable/tag_status_gray)}"
android:paddingHorizontal="8dp"
android:paddingVertical="2dp"
android:text="@{bean.arriveFlagText}"
android:textColor="@{`0`.equals(bean.arriveFlag) ? @color/text_green : (`1`.equals(bean.arriveFlag) ? @color/text_orange : @color/text_gray)}"
android:textSize="14sp"
android:visibility="@{bean.arriveFlag != null &amp;&amp; !bean.arriveFlag.isEmpty() ? View.VISIBLE : View.GONE}" />
</LinearLayout>
<!-- 运单类型 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单类型:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.awbName}"
android:textColor="@color/text_normal"
android:textSize="15sp" />
</LinearLayout>
<!-- 分单数 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分单数:"
android:textColor="@color/text_normal"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(bean.haWbNumber)}"
android:textColor="@color/text_normal"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<!-- 展开按钮 -->
<ImageView
android:id="@+id/iv_show"
android:layout_width="match_parent"
android:layout_height="20dp"
android:paddingVertical="2.5dp"
android:layout_marginTop="-20dp"
android:scaleType="center"
android:src="@mipmap/img_down" />
</LinearLayout>
<!-- 子订单列表容器(白色圆角卡片,圆角同主单) -->
<LinearLayout
visible="@{bean.showMore}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@drawable/bg_white_radius_8"
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone"> android:padding="14dp">
<!-- 暂无数据提示 --> <!-- 头行:(选择圈,仅待运抵)运单号 + 状态标签 -->
<TextView
android:id="@+id/tv_empty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingVertical="15dp"
android:text="暂无分单数据"
android:textColor="@color/text_gray"
android:textSize="14sp"
android:visibility="gone" />
<!-- 表头(浅蓝色背景,仅 Title 有背景色,顶部圆角同卡片) -->
<LinearLayout <LinearLayout
android:id="@+id/ll_header"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/bg_arrive_sub_header" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal">
android:paddingHorizontal="10dp"
android:paddingVertical="10dp">
<TextView <ImageView
android:layout_width="0dp" android:id="@+id/iv_select"
android:layout_height="wrap_content" android:layout_width="20dp"
android:layout_weight="0.5" android:layout_height="20dp"
android:gravity="center" android:layout_marginEnd="8dp"
android:text="选项" loadImage="@{bean.checked.get() ? @drawable/radiobtn_checked_style : @drawable/radiobtn_unchecked_style}"
android:textColor="@color/text_normal" android:src="@drawable/radiobtn_unchecked_style"
android:textSize="14sp" android:visibility="@{`pending`.equals(viewModel.currentTab) ? View.VISIBLE : View.GONE}" />
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.2"
android:gravity="center"
android:text="分单号"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center"
android:text="件数"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center"
android:text="重量(KG)"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView <TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center" android:text="@{bean.wbNo}"
android:text="申报状态" android:textColor="@color/phone_text_strong"
android:textColor="@color/text_normal" android:textSize="15sp"
android:textSize="14sp" android:textStyle="bold"
android:textStyle="bold" /> tools:text="78133363396" />
<!-- 提前运抵(待运抵 Tab仅 arriveFlag=1 时显示) -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_tag_red"
android:paddingHorizontal="8dp"
android:paddingVertical="3dp"
android:text="提前运抵"
android:textColor="@color/phone_tag_red_text"
android:textSize="11sp"
android:visibility="@{`pending`.equals(viewModel.currentTab) &amp;&amp; `1`.equals(bean.arriveFlag) ? View.VISIBLE : View.GONE}" />
<!-- 申报状态(已运抵 Tab三色 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@{`green`.equals(bean.declareTagColor) ? @drawable/bg_phone_tag_green : (`indigo`.equals(bean.declareTagColor) ? @drawable/bg_phone_tag_indigo : @drawable/bg_phone_tag_amber)}"
android:paddingHorizontal="8dp"
android:paddingVertical="3dp"
android:text="@{bean.declareStatus}"
android:textColor="@{`green`.equals(bean.declareTagColor) ? @color/phone_tag_green_text : (`indigo`.equals(bean.declareTagColor) ? @color/phone_tag_indigo_text : @color/phone_tag_amber_text)}"
android:textSize="11sp"
android:visibility="@{`shipped`.equals(viewModel.currentTab) &amp;&amp; !bean.declareTagColor.empty ? View.VISIBLE : View.GONE}"
tools:text="01" />
</LinearLayout>
<!-- 字段网格:代理 / 件数 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<TextView <TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center" android:text='@{"代理: " + bean.agentName}'
android:text="品名(中)" android:textColor="@color/phone_text_body"
android:textColor="@color/text_normal" android:textSize="13sp"
android:textSize="14sp" tools:text="代理: 马道" />
android:textStyle="bold" />
<TextView <TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="0.9" android:layout_weight="1"
android:gravity="center" android:text='@{"件数: " + bean.pc}'
android:text="申报次数" android:textColor="@color/phone_text_body"
android:textColor="@color/text_normal" android:textSize="13sp"
android:textSize="14sp" tools:text="件数: 444" />
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.9"
android:gravity="center"
android:text="申报费率"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.9"
android:gravity="center"
android:text="删除次数"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.9"
android:gravity="center"
android:text="删除费率"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout> </LinearLayout>
<com.google.android.material.divider.MaterialDivider <!-- 字段网格:重量 / 航班日期 -->
android:id="@+id/divider_header" <LinearLayout
android:layout_width="match_parent"
android:layout_height="1px"
app:dividerColor="@color/sub_list_divider" />
<!-- 子列表 RecyclerView -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_sub"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" /> android:layout_marginTop="8dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"重量: " + (int) bean.weight + "kg"}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="重量: 150kg" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"航班日期: " + bean.flightDateText}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="航班日期: 20260713" />
</LinearLayout> </LinearLayout>
<!-- 字段网格:航班号 / 航程 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"航班号: " + bean.fno}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="航班号: MU2033" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"航程: " + bean.rangeText}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="航程: HFE-LAX" />
</LinearLayout> </LinearLayout>
<!-- 查看分单(无分单数据时不显示) -->
<TextView
android:layout_width="match_parent"
android:layout_height="36dp"
android:layout_marginTop="12dp"
android:background="@drawable/bg_phone_btn_weak"
android:gravity="center"
android:onClick="@{()-> activity.openSubOrder(bean)}"
android:text='@{"查看分单 " + bean.haWbNumber}'
android:textColor="@color/phone_primary"
android:textSize="14sp"
android:visibility="@{bean.haWbNumber != null &amp;&amp; bean.haWbNumber > 0 ? View.VISIBLE : View.GONE}"
tools:text="查看分单 3" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- ==================== 长按操作浮层 ==================== -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#66000000"
android:clickable="true"
android:onClick="@{()-> activity.hideCardActionPhone(bean)}"
android:visibility="@{bean.actionMenuVisible ? View.VISIBLE : View.GONE}">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal">
<!-- 补充(仅待运抵) -->
<TextView
android:layout_width="56dp"
android:layout_height="56dp"
android:background="@drawable/bg_phone_fab_purple"
android:gravity="center"
android:onClick="@{()-> activity.openSupplement(bean)}"
android:text="补充"
android:textColor="@color/white"
android:textSize="12sp"
android:textStyle="bold"
android:visibility="@{`pending`.equals(viewModel.currentTab) ? View.VISIBLE : View.GONE}" />
<!-- 重置(仅已运抵) -->
<TextView
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginEnd="16dp"
android:background="@drawable/bg_phone_fab_amber"
android:gravity="center"
android:onClick="@{()-> viewModel.resetSingleDeclareClick(bean)}"
android:text="重置"
android:textColor="@color/white"
android:textSize="12sp"
android:textStyle="bold"
android:visibility="@{`shipped`.equals(viewModel.currentTab) ? View.VISIBLE : View.GONE}" />
<!-- 回执(仅已运抵) -->
<TextView
android:layout_width="56dp"
android:layout_height="56dp"
android:background="@drawable/bg_phone_fab_green"
android:gravity="center"
android:onClick="@{()-> activity.openReceipt(bean)}"
android:text="回执"
android:textColor="@color/white"
android:textSize="12sp"
android:textStyle="bold"
android:visibility="@{`shipped`.equals(viewModel.currentTab) ? View.VISIBLE : View.GONE}" />
</LinearLayout>
</FrameLayout>
</FrameLayout>
</layout> </layout>

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 国际出港运抵-回执内容 - 单条回执卡片5.5寸手机版专属只读页) -->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="bean"
type="com.lukouguoji.module_base.bean.GjcHaWb" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="10dp"
android:background="@drawable/bg_phone_card"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<View
android:layout_width="6dp"
android:layout_height="6dp"
android:layout_marginTop="7dp"
android:background="@drawable/bg_phone_fab" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:text="@{bean.response}"
android:textColor="@color/phone_text_strong"
android:textSize="14sp"
tools:text="单一窗口回执内容45201 空运出口运抵报告传输成功。比对结果为:运抵正常。" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:text="@{bean.arrivalOpDateText}"
android:textColor="@color/phone_text_hint"
android:textSize="12sp"
tools:text="2026-07-10 11:03:38" />
</LinearLayout>
</layout>

View File

@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
国际出港运抵-分单明细 - 分单卡片5.5寸手机版专属页面)
对应设计稿卡片:分单号 + 申报状态标签 + 件数/重量,长按弹出「重置」单条操作。
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="bean"
type="com.lukouguoji.module_base.bean.GjcHaWb" />
<variable
name="activity"
type="com.lukouguoji.gjc.activity.IntExpArriveSubOrderActivity" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="10dp">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card"
android:onLongClick="@{()-> activity.showActionMenu(bean)}"
android:orientation="vertical"
android:padding="14dp">
<!-- 头行:选择圈 + 分单号 + 申报状态标签 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginEnd="8dp"
loadImage="@{bean.checked.get() ? @drawable/radiobtn_checked_style : @drawable/radiobtn_unchecked_style}"
android:src="@drawable/radiobtn_unchecked_style" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@{bean.hno}"
android:textColor="@color/phone_text_strong"
android:textSize="15sp"
android:textStyle="bold"
tools:text="10001" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@{`green`.equals(bean.haWbTagColor) ? @drawable/bg_phone_tag_green : (`indigo`.equals(bean.haWbTagColor) ? @drawable/bg_phone_tag_indigo : @drawable/bg_phone_tag_amber)}"
android:paddingHorizontal="8dp"
android:paddingVertical="3dp"
android:text="@{bean.arrivalStatus}"
android:textColor="@{`green`.equals(bean.haWbTagColor) ? @color/phone_tag_green_text : (`indigo`.equals(bean.haWbTagColor) ? @color/phone_tag_indigo_text : @color/phone_tag_amber_text)}"
android:textSize="11sp"
android:visibility="@{bean.haWbTagColor.empty ? View.GONE : View.VISIBLE}"
tools:text="W" />
</LinearLayout>
<!-- 字段网格:件数 / 重量 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"件数: " + (bean.hpc != null ? bean.hpc : bean.pc)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="件数: 150" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"重量: " + (int)(bean.hweight != null ? bean.hweight : bean.weight) + "kg"}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="重量: 50kg" />
</LinearLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- ==================== 长按操作浮层:仅「重置」 ==================== -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#66000000"
android:clickable="true"
android:onClick="@{()-> activity.hideActionMenu(bean)}"
android:visibility="@{bean.actionMenuVisible ? View.VISIBLE : View.GONE}">
<TextView
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_gravity="center"
android:background="@drawable/bg_phone_fab_amber"
android:gravity="center"
android:onClick="@{()-> activity.resetSingleClick(bean)}"
android:text="重置"
android:textColor="@color/white"
android:textSize="12sp"
android:textStyle="bold" />
</FrameLayout>
</FrameLayout>
</layout>

View File

@@ -54,6 +54,12 @@ class GjViewModel : BaseViewModel() {
Constant.AuthName.GjcCheckWeighing, Constant.AuthName.GjcCheckWeighing,
ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_LIST ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_LIST
), ),
ActionBean(
"出港运抵",
R.drawable.img_gjc_chugang_diyun,
Constant.AuthName.GjcIntExpArrive,
ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE
),
// ULD管理属综合管理业务Pad 端在「综合管理」菜单组),手机端首页暂无综合 Tab挂在国际 Tab 下 // ULD管理属综合管理业务Pad 端在「综合管理」菜单组),手机端首页暂无综合 Tab挂在国际 Tab 下
ActionBean( ActionBean(
"ULD管理", "ULD管理",

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB