fix: 出港运抵手机端对照设计稿review修正与重置弹框适配

- 状态重置弹框改手机底部弹层:dialog 布局同名双变体(Pad 移 layout-sw600dp),
  弹出位置按形态切 DIALOG_TYPE_BOTTOM/CENTER,为弹框适配首例
- 主列表补空态(文案按 Tab 切换)、回执页补「暂无回执内容」兜底
- 分单明细长按浮层按设计稿补「回执」按钮;底部统计加分母「已选 N / M 项」
- Tab 角标初始显示 0
- PhoneStatusTab/PhoneFilterPanel 补 dispatchSave/RestoreInstanceState 状态屏蔽(历史遗漏)
- 双端实机验证:手机端各修正点与设计稿一致且 crash=0;平板端列表与批量重置弹框回归无变化

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-30 23:21:33 +08:00
parent ef8e7cfacb
commit 436202f15b
14 changed files with 348 additions and 101 deletions

View File

@@ -67,6 +67,12 @@ class IntExpArriveSubOrderActivity :
viewModel.resetSingleClick(bean)
}
/** 长按菜单「回执」(单条):复用回执只读页,仅传当前分单 */
fun openReceipt(bean: GjcHaWb) {
bean.actionMenuVisible.set(false)
IntExpArriveReceiptActivity.start(this, viewModel.wbNo, arrayListOf(bean))
}
fun toggleFilterPanel() {
filterPanelVisible.set(!filterPanelVisible.get())
}

View File

@@ -6,14 +6,20 @@ import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.databinding.DialogIntExpArriveResetBinding
import com.lukouguoji.module_base.base.BaseDialogModel
import com.lukouguoji.module_base.ktx.verifyNullOrEmpty
import com.lukouguoji.module_base.util.DeviceUtil
import dev.utils.app.info.KeyValue
/**
* 国际出港运抵 - 状态重置对话框
*
* 布局按资源限定符自动切换:手机 layout/(底部弹层)、平板 layout-sw600dp/(居中弹框),
* 弹出位置随形态选择 BOTTOM/CENTER。
*/
class IntExpArriveResetDialogModel(
private val callback: (IntExpArriveResetDialogModel) -> Unit
) : BaseDialogModel<DialogIntExpArriveResetBinding>(DIALOG_TYPE_CENTER) {
) : BaseDialogModel<DialogIntExpArriveResetBinding>(
if (DeviceUtil.isPhone()) DIALOG_TYPE_BOTTOM else DIALOG_TYPE_CENTER
) {
// 重置状态列表
val resetStatusList = MutableLiveData<List<KeyValue>>()

View File

@@ -65,7 +65,11 @@ class IntExpArriveViewModel : BasePageViewModel() {
)
/** 两个 Tab 的角标计数(当前已加载数据的客户端统计,非全量,见接口问题清单) */
val arriveTabCounts = MutableLiveData(listOf("", ""))
val arriveTabCounts = MutableLiveData(listOf("0", "0"))
/** 手机版空态(当前 Tab 过滤后无数据时显示,对应设计稿 empty-pending */
val emptyVisiblePhone = MutableLiveData(false)
val emptyTextPhone = MutableLiveData("暂无待运抵的运单")
/** 手机版全选状态(仅统计待运抵 Tab 内的项,与 Pad 端 [isAllChecked] 统计口径不同) */
val isAllCheckedPhone = MutableLiveData(false)
@@ -116,6 +120,8 @@ class IntExpArriveViewModel : BasePageViewModel() {
val isPendingTab = currentTab.value == "pending"
val filtered = allLoadedList.filter { it.isPending == isPendingTab }
pageModel.rv?.commonAdapter()?.refresh(filtered)
emptyVisiblePhone.value = filtered.isEmpty()
emptyTextPhone.value = if (isPendingTab) "暂无待运抵的运单" else "暂无已运抵的运单"
updateCheckAllStatusPhone()
}

View File

@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.lukouguoji.module_base.ui.weight.search.layout.SearchLayoutType"/>
<variable
name="model"
type="com.lukouguoji.gjc.dialog.IntExpArriveResetDialogModel" />
</data>
<LinearLayout
android:layout_width="480dp"
android:layout_height="wrap_content"
android:background="@drawable/bg_dialog_f2_radius_10"
android:gravity="center_horizontal"
android:orientation="vertical">
<!-- 标题栏 -->
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/bg_primary_radius_top_10"
android:gravity="center"
android:text="状态重置"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold" />
<!-- 表单内容 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="30dp"
android:layout_marginTop="30dp"
android:orientation="vertical">
<!-- 重置状态 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{5}"
android:text="重置状态:"
android:textColor="@color/text_normal"
android:textSize="16sp" />
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
type="@{SearchLayoutType.SPINNER}"
hint='@{"请选择重置状态"}'
list="@{model.resetStatusList}"
value="@={model.selectedResetStatus}" />
</LinearLayout>
</LinearLayout>
<!-- 底部按钮 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:layout_marginBottom="20dp">
<TextView
style="@style/tv_bottom_btn"
android:onClick="@{()->model.dismiss()}"
android:text="取消" />
<TextView
style="@style/tv_bottom_btn"
android:onClick="@{()->model.onSaveClick()}"
android:text="确定" />
</LinearLayout>
</LinearLayout>
</layout>

View File

@@ -89,19 +89,51 @@
android:layout_height="0dp"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
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="2"
tools:listitem="@layout/item_int_exp_arrive" />
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
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="2"
tools:listitem="@layout/item_int_exp_arrive" />
<!-- 空态(对应设计稿 empty-pending图标 + 文案,按当前 Tab 切换) -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:visibility="@{viewModel.emptyVisiblePhone ? View.VISIBLE : View.GONE}">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_phone_clipboard"
android:tint="@color/phone_text_hint" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@{viewModel.emptyTextPhone}"
android:textColor="@color/phone_text_hint"
android:textSize="14sp"
tools:text="暂无待运抵的运单" />
</LinearLayout>
</FrameLayout>
</com.scwang.smart.refresh.layout.SmartRefreshLayout>

View File

@@ -11,6 +11,8 @@
<data>
<import type="android.view.View" />
<variable
name="viewModel"
type="com.lukouguoji.gjc.viewModel.IntExpArriveReceiptViewModel" />
@@ -24,20 +26,51 @@
<include layout="@layout/title_tool_bar" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
<FrameLayout
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" />
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
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
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:visibility="@{viewModel.receiptList.empty ? View.VISIBLE : View.GONE}">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_phone_clipboard"
android:tint="@color/phone_text_hint" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="暂无回执内容"
android:textColor="@color/phone_text_hint"
android:textSize="14sp" />
</LinearLayout>
</FrameLayout>
</LinearLayout>

View File

@@ -82,7 +82,7 @@
android:layout_height="wrap_content"
actionText='@{"申报"}'
allChecked="@{viewModel.isAllChecked}"
countText='@{"已选 " + viewModel.selectedCount + " 项"}'
countText='@{"已选 " + viewModel.selectedCount + " / " + viewModel.displayList.size() + " 项"}'
setOnActionClick="@{(v)-> viewModel.declareClick()}"
setOnAllCheckClick="@{(v)-> activity.checkAllClick()}" />

View File

@@ -1,8 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
状态重置弹框手机版5.5 寸手持端)
对应设计稿 04_出港运抵/main.html 的 reset-sheet 底部弹层:
标题「重置状态」+ 右上关闭 + 「状态」下拉 + 全宽主色「确定」按钮。
平板变体layout-sw600dp/dialog_int_exp_arrive_reset.xml居中弹框
弹出位置由 IntExpArriveResetDialogModel 按设备形态选择 BOTTOM/CENTER。
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.lukouguoji.module_base.ui.weight.search.layout.SearchLayoutType"/>
<import type="com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayoutType" />
<variable
name="model"
@@ -11,77 +19,60 @@
</data>
<LinearLayout
android:layout_width="480dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_dialog_f2_radius_10"
android:gravity="center_horizontal"
android:orientation="vertical">
android:background="@drawable/bg_phone_panel_top"
android:orientation="vertical"
android:paddingHorizontal="20dp"
android:paddingTop="24dp"
android:paddingBottom="32dp">
<!-- 标题 -->
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/bg_primary_radius_top_10"
android:gravity="center"
android:text="状态重置"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold" />
<!-- 表单内容 -->
<LinearLayout
<!-- 标题行:标题居中 + 右上关闭 -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="30dp"
android:layout_marginTop="30dp"
android:orientation="vertical">
android:layout_marginBottom="24dp">
<!-- 重置状态 -->
<LinearLayout
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
android:gravity="center"
android:text="重置状态"
android:textColor="@color/phone_text_strong"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{5}"
android:text="重置状态:"
android:textColor="@color/text_normal"
android:textSize="16sp" />
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="end|center_vertical"
android:onClick="@{()-> model.dismiss()}"
android:src="@drawable/ic_phone_close" />
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
type="@{SearchLayoutType.SPINNER}"
hint='@{"请选择重置状态"}'
list="@{model.resetStatusList}"
value="@={model.selectedResetStatus}" />
</FrameLayout>
</LinearLayout>
</LinearLayout>
<!-- 底部按钮 -->
<LinearLayout
android:layout_width="wrap_content"
<!-- 状态下拉 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:layout_marginBottom="20dp">
hint='@{"请选择状态"}'
list="@{model.resetStatusList}"
title='@{"状态"}'
type="@{PhoneDataLayoutType.SPINNER}"
value="@={model.selectedResetStatus}" />
<TextView
style="@style/tv_bottom_btn"
android:onClick="@{()->model.dismiss()}"
android:text="取消" />
<TextView
style="@style/tv_bottom_btn"
android:onClick="@{()->model.onSaveClick()}"
android:text="确定" />
</LinearLayout>
<!-- 确定按钮 -->
<TextView
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="32dp"
android:background="@drawable/bg_phone_btn_primary"
android:gravity="center"
android:onClick="@{()-> model.onSaveClick()}"
android:text="确定"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</layout>

View File

@@ -2,7 +2,7 @@
<!--
国际出港运抵-分单明细 - 分单卡片5.5寸手机版专属页面)
对应设计稿卡片:分单号 + 申报状态标签 + 件数/重量,长按弹出「重置」单条操作。
对应设计稿卡片:分单号 + 申报状态标签 + 件数/重量,长按弹出「重置」+「回执」单条操作。
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
@@ -102,7 +102,7 @@
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- ==================== 长按操作浮层:「重置」 ==================== -->
<!-- ==================== 长按操作浮层:「重置」+「回执」(对应设计稿双圆按钮) ==================== -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -111,17 +111,36 @@
android:onClick="@{()-> activity.hideActionMenu(bean)}"
android:visibility="@{bean.actionMenuVisible ? View.VISIBLE : View.GONE}">
<TextView
android:layout_width="56dp"
android:layout_height="56dp"
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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" />
android:orientation="horizontal">
<TextView
android:layout_width="56dp"
android:layout_height="56dp"
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" />
<TextView
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginStart="24dp"
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" />
</LinearLayout>
</FrameLayout>