feat: 完成提取出库页面5.5寸手机端适配

提取出库(09,module_gjj):
- IntImpPickUpDLVActivity 手机布局:搜索行+待出库/已出库状态Tab(outState 为
  pageQuery 文档定义入参 0/1,Tab 真实过滤+角标双 pageQueryTotal,抓包证实携带)
  +双形态卡片(isPickedUp=dlvTime非空:待出库勾选框+橙标签+库位行/已出库绿√+
  出库人·出库时间行)+卡片内 PhoneStatBox 三列+PhoneBottomBar(仅待出库Tab显示,
  复用既有 confirmOutbound)
- 手机专属新页 IntImpPickUpDetailActivity 运单详情:蓝头运单卡+绿头提货信息卡,
  Intent 传 Serializable bean 零新增请求
- 筛选弹层 4 项(航班日期为未定义入参预留传参);手机进入时清空平板默认
  「当天缴费日期」查全量,平板默认值不变
- IntImpPickUpDLVBean 增加 isPickedUp 计算属性;手机首页「国际」Tab 加入口

修复:checkAllClick 全选后底部「已选 N 项」不更新(批量勾选不走单卡 FlowBus
事件,需自行同步 selectedCountText),实测修复生效

验证:双端 Proxyman Map Local mock 口径验证通过,平板回归一致(含缴费日期默认值),
崩溃 0;后端缺口 2 项登记问题清单 #28~#29(无 fdate 入参、出参无车牌/目的港/
业务类型;outState 过滤与 dlvName=出库人语义待内网实测)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-31 21:31:58 +08:00
parent 3b732c3aec
commit b2a2cce585
18 changed files with 1369 additions and 409 deletions

View File

@@ -13,6 +13,7 @@ import com.lukouguoji.module_base.common.ConstantEvent
import com.lukouguoji.module_base.impl.FlowBus
import com.lukouguoji.module_base.impl.observe
import com.lukouguoji.module_base.router.ARouterConstants
import com.lukouguoji.module_base.util.DeviceUtil
/**
* 国际进港-提取出库
@@ -25,9 +26,12 @@ class IntImpPickUpDLVActivity :
override fun viewModelClass() = IntImpPickUpDLVViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("国际进港出库")
setBackArrow(if (DeviceUtil.isPhone()) "提取出库" else "国际进港出库")
binding.viewModel = viewModel
// 手机形态专属:待出库 Tab 默认态 + 角标计数 + 特码字典(平板不调用,行为零变化)
if (DeviceUtil.isPhone()) viewModel.initPhoneExtras()
// 绑定分页
viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this)

View File

@@ -0,0 +1,45 @@
package com.lukouguoji.gjj.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.lukouguoji.gjj.R
import com.lukouguoji.gjj.databinding.ActivityIntImpPickUpDetailBinding
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.base.BaseViewModel
import com.lukouguoji.module_base.bean.IntImpPickUpDLVBean
import com.lukouguoji.module_base.common.Constant
/**
* 国际进港提取出库-运单详情(5.5 寸手机版专属页面)
*
* 设计稿 09_提取出库「查看详情」内嵌页:蓝头运单卡(品名/件重/特码/代理/港站/航班/库位/提货单号)
* + 绿头提货信息卡(柜台办理人/时间,已出库追加出库人/出库时间)。
* 数据直接复用列表已加载的 bean(Intent 传 Serializable),零新增请求;平板端无入口不可达。
*/
class IntImpPickUpDetailActivity :
BaseBindingActivity<ActivityIntImpPickUpDetailBinding, BaseViewModel>() {
override fun layoutId() = R.layout.activity_int_imp_pick_up_detail
override fun viewModelClass() = BaseViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("运单详情")
val bean = intent.getSerializableExtra(Constant.Key.DATA) as? IntImpPickUpDLVBean
if (bean == null) {
finish()
return
}
binding.bean = bean
}
companion object {
@JvmStatic
fun start(context: Context, bean: IntImpPickUpDLVBean) {
context.startActivity(
Intent(context, IntImpPickUpDetailActivity::class.java)
.putExtra(Constant.Key.DATA, bean)
)
}
}
}

View File

@@ -1,6 +1,7 @@
package com.lukouguoji.gjj.holder
import android.view.View
import com.lukouguoji.gjj.activity.IntImpPickUpDetailActivity
import com.lukouguoji.gjj.databinding.ItemIntImpPickUpDlvBinding
import com.lukouguoji.module_base.base.BaseViewHolder
import com.lukouguoji.module_base.common.ConstantEvent
@@ -9,6 +10,9 @@ import com.lukouguoji.module_base.bean.IntImpPickUpDLVBean
/**
* 国际进港-提取出库 列表项ViewHolder
*
* 双形态布局:平板变体含 iv_icon(多选图标),手机变体含 iv_check(圆形勾选框,仅待出库形态显示)
* 与 tv_detail(查看详情)。单侧独有的 id 在 Binding 基类中为 @Nullable,必须判空访问。
*/
class IntImpPickUpDLVViewHolder(view: View) :
BaseViewHolder<IntImpPickUpDLVBean, ItemIntImpPickUpDlvBinding>(view) {
@@ -19,11 +23,25 @@ class IntImpPickUpDLVViewHolder(view: View) :
binding.position = position
binding.executePendingBindings()
// 点击图标切换选中状态
binding.ivIcon.setOnClickListener {
// 平板:点击图标切换选中状态
binding.ivIcon?.setOnClickListener {
bean.checked.set(!bean.checked.get())
FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED).tryEmit("check_changed")
binding.executePendingBindings()
}
// 手机:圆形勾选框(已出库形态隐藏,无勾选语义)
binding.ivCheck?.setOnClickListener {
if (!bean.isPickedUp) {
bean.checked.set(!bean.checked.get())
FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED).tryEmit("check_changed")
binding.executePendingBindings()
}
}
// 手机:查看详情(手机专属新页,数据直接传当前 bean,零新增请求)
binding.tvDetail?.setOnClickListener {
IntImpPickUpDetailActivity.start(itemView.context, bean)
}
}
}

View File

@@ -20,6 +20,7 @@ import com.lukouguoji.module_base.ktx.formatDate
import com.lukouguoji.module_base.ktx.toRequestBody
import com.lukouguoji.module_base.model.ConfirmDialogModel
import com.lukouguoji.module_base.model.ScanModel
import com.lukouguoji.module_base.util.DictUtils
import dev.utils.app.info.KeyValue
import dev.utils.common.DateUtils
import kotlinx.coroutines.launch
@@ -54,6 +55,68 @@ class IntImpPickUpDLVViewModel : BasePageViewModel() {
fun updateCheckAllStatus() {
val list = pageModel.rv?.commonAdapter()?.items as? List<IntImpPickUpDLVBean> ?: return
isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() }
selectedCountText.value = "已选 ${list.count { it.checked.get() }} 项"
}
// ========== 5.5寸手机版专属 ==========
// 状态 Tab:待出库/已出库(outState 为 pageQuery 真实入参,0:未出库,1:已出库;平板恒空不进请求)
val outState = MutableLiveData("")
val tabList = MutableLiveData(listOf(KeyValue("待出库", "0"), KeyValue("已出库", "1")))
val tabCounts = MutableLiveData(listOf("0", "0"))
// 底部操作条「已选 N 项」
val selectedCountText = MutableLiveData("已选 0 项")
// 筛选弹层显隐
val filterVisible = MutableLiveData(false)
// 筛选条件(flightDate 为 pageQuery 未定义入参 fdate,预留传参,见接口问题清单)
val flightDate = MutableLiveData("")
val flightNo = MutableLiveData("")
// 特码下拉字典(initPhoneExtras 加载,平板为扫码输入不加载)
val specialCodeList = MutableLiveData<List<KeyValue>>(emptyList())
private var phoneExtrasEnabled = false
/**
* 手机形态专属初始化(Activity 在 DeviceUtil.isPhone() 时调用)。
* 平板端不调用,请求次数与行为零变化。
*/
fun initPhoneExtras() {
phoneExtrasEnabled = true
// 默认进「待出库」Tab
outState.value = "0"
// 平板默认按当天缴费日期过滤,设计稿无此默认——手机端清空查全量
paymentDateStart.value = ""
// 特码字典:flag=1 国际;ieFlag 必须留空
DictUtils.getSpecialCodeList(addAll = false, flag = 1, ieFlag = "") { list ->
specialCodeList.postValue(listOf(KeyValue("全部", "")) + list)
}
}
/** 筛选按钮点击 - 打开筛选面板 */
fun filterClick() {
filterVisible.value = true
}
/** 关闭筛选面板 */
fun closeFilter() {
filterVisible.value = false
}
/** 重置筛选条件 */
fun resetFilter() {
flightDate.value = ""
flightNo.value = ""
agentCode.value = ""
spCode.value = ""
}
/** 确认筛选 - 关闭面板并刷新 */
fun confirmFilter() {
filterVisible.value = false
refresh()
}
// ========== 适配器配置 ==========
@@ -105,6 +168,8 @@ class IntImpPickUpDLVViewModel : BasePageViewModel() {
list.forEach { it.checked.set(shouldCheckAll) }
isAllChecked.value = shouldCheckAll
pageModel.rv?.commonAdapter()?.notifyDataSetChanged()
// 同步手机版底部条「已选 N 项」(平板布局不绑定该字段,无影响)
selectedCountText.value = "已选 ${list.count { it.checked.get() }} 项"
}
/**
@@ -139,12 +204,17 @@ class IntImpPickUpDLVViewModel : BasePageViewModel() {
* 获取列表数据
*/
override fun getData() {
// 手机专属 3 项平板恒为空,不进请求;fdate 为 pageQuery 未定义入参
//(后端静默忽略,补齐后自动生效,见接口问题清单)
val filterParams = mapOf(
"beginDate" to paymentDateStart.value?.ifEmpty { null },
"endDate" to paymentDateEnd.value?.ifEmpty { null },
"agentCode" to agentCode.value?.ifEmpty { null },
"no" to wbNo.value?.ifEmpty { null },
"spCode" to spCode.value?.ifEmpty { null }
"spCode" to spCode.value?.ifEmpty { null },
"outState" to outState.value?.ifEmpty { null },
"fno" to flightNo.value?.ifEmpty { null },
"fdate" to flightDate.value?.ifEmpty { null }
)
val listParams = (filterParams + mapOf(
@@ -169,6 +239,28 @@ class IntImpPickUpDLVViewModel : BasePageViewModel() {
totalWeight.value = (data?.totalWeight ?: 0.0).toString()
}
}
// 手机专属:Tab 角标计数(同条件 + outState=0/1 各查一次,平板不发)
if (phoneExtrasEnabled) {
val pendingParams = (filterParams + mapOf("outState" to "0")).toRequestBody()
launchCollect({ NetApply.api.getIntImpPickUpDLVTotal(pendingParams) }) {
onSuccess = { result ->
tabCounts.value = listOf(
(result.data?.wbNumber ?: 0).toString(),
tabCounts.value?.getOrNull(1) ?: "0"
)
}
}
val shippedParams = (filterParams + mapOf("outState" to "1")).toRequestBody()
launchCollect({ NetApply.api.getIntImpPickUpDLVTotal(shippedParams) }) {
onSuccess = { result ->
tabCounts.value = listOf(
tabCounts.value?.getOrNull(0) ?: "0",
(result.data?.wbNumber ?: 0).toString()
)
}
}
}
}
/**