feat: 国际出港开始组装板型下拉改为控件下方展开

板型由底部弹框选择改为锚定在输入框正下方的 ListPopupWindow,
复用相邻 BUP Spinner 的弹层背景与列表项布局,外观保持一致,
且不影响手动输入。

板型数据源的承运人参数改由 ULD 编号触发:选中运单不再重载,
改为 ULD 信息查询成功后取 ULD 编号后两位作为 carrier 重新加载。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-17 11:49:06 +08:00
parent 6b02f71e8a
commit f39127436a
3 changed files with 64 additions and 27 deletions

View File

@@ -5,6 +5,10 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.ArrayAdapter
import androidx.appcompat.widget.AppCompatSpinner
import androidx.appcompat.widget.ListPopupWindow
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.alibaba.android.arouter.facade.annotation.Route import com.alibaba.android.arouter.facade.annotation.Route
import com.lukouguoji.gjc.R import com.lukouguoji.gjc.R
@@ -19,6 +23,7 @@ import com.lukouguoji.module_base.impl.observe
import com.lukouguoji.module_base.interfaces.IOnItemClickListener import com.lukouguoji.module_base.interfaces.IOnItemClickListener
import com.lukouguoji.module_base.ktx.addOnItemClickListener import com.lukouguoji.module_base.ktx.addOnItemClickListener
import com.lukouguoji.module_base.ktx.setUpperCaseAlphanumericFilter import com.lukouguoji.module_base.ktx.setUpperCaseAlphanumericFilter
import com.lukouguoji.module_base.ktx.showToast
import com.lukouguoji.module_base.router.ARouterConstants import com.lukouguoji.module_base.router.ARouterConstants
/** /**
@@ -29,6 +34,7 @@ class IntExpAssembleStartActivity :
BaseBindingActivity<ActivityIntExpAssembleStartBinding, IntExpAssembleStartViewModel>(), BaseBindingActivity<ActivityIntExpAssembleStartBinding, IntExpAssembleStartViewModel>(),
IOnItemClickListener { IOnItemClickListener {
private var boardTypePopup: ListPopupWindow? = null
private var assembleInfoAdapter: CommonAdapter? = null private var assembleInfoAdapter: CommonAdapter? = null
private var assemblePositionAdapter: CommonAdapter? = null private var assemblePositionAdapter: CommonAdapter? = null
private var waybillAdapter: CommonAdapter? = null private var waybillAdapter: CommonAdapter? = null
@@ -72,11 +78,12 @@ class IntExpAssembleStartActivity :
binding.impCodeInput.et.setUpperCaseAlphanumericFilter() binding.impCodeInput.et.setUpperCaseAlphanumericFilter()
// 板型:手动输入 + 下拉选择组合框。箭头复用 Spinner 同款背景绘制(同资源、同尺寸、同边距), // 板型:手动输入 + 下拉选择组合框。箭头复用 Spinner 同款背景绘制(同资源、同尺寸、同边距),
// 图标位不放图片,仅作为覆盖在箭头上的透明点击区域(点击事件由布局 setOnIconClickListener 绑定) // 图标位不放图片,仅作为覆盖在箭头上的透明点击区域
binding.boardTypeInput.apply { binding.boardTypeInput.apply {
ll.setBackgroundResource(com.lukouguoji.module_base.R.drawable.bg_data_layout_new_dropdown) ll.setBackgroundResource(com.lukouguoji.module_base.R.drawable.bg_data_layout_new_dropdown)
iv.setImageDrawable(null) iv.setImageDrawable(null)
iv.visibility = View.VISIBLE iv.visibility = View.VISIBLE
iv.setOnClickListener { showBoardTypeDropdown() }
} }
// 初始化列表 // 初始化列表
@@ -106,6 +113,51 @@ class IntExpAssembleStartActivity :
handleEditModeIntent() handleEditModeIntent()
} }
/**
* 板型下拉:锚定在板型输入框正下方展开(外观与相邻 BUP 的 Spinner 下拉一致),选中后回填,仍可手动输入
*/
private fun showBoardTypeDropdown() {
val list = viewModel.boardTypeList.value ?: emptyList()
if (list.isEmpty()) {
showToast("暂无板型选项,请手动输入")
return
}
val anchor = binding.boardTypeInput.ll
// 先收起软键盘,避免下拉被输入法遮挡
(getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)
?.hideSoftInputFromWindow(anchor.windowToken, 0)
boardTypePopup?.dismiss()
boardTypePopup = ListPopupWindow(this).apply {
anchorView = anchor
width = anchor.width
isModal = true
// 复用 BUP Spinner 的弹窗背景,保证两者下拉外观完全一致
(binding.bupFlagInput.spinner as? AppCompatSpinner)?.popupBackground
?.constantState?.newDrawable()?.mutate()
?.let { setBackgroundDrawable(it) }
setAdapter(
ArrayAdapter(
this@IntExpAssembleStartActivity,
com.lukouguoji.module_base.R.layout.item_spinner_list,
list.map { it.key }
)
)
setOnItemClickListener { _, _, position, _ ->
viewModel.onBoardTypeSelected(position)
dismiss()
}
show()
}
}
override fun onDestroy() {
boardTypePopup?.dismiss()
boardTypePopup = null
super.onDestroy()
}
/** /**
* 处理修改模式的 Intent 参数 * 处理修改模式的 Intent 参数
*/ */

View File

@@ -2,7 +2,6 @@ package com.lukouguoji.gjc.viewModel
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.alibaba.fastjson.JSONArray
import com.lukouguoji.gjc.R import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.holder.AssembleInfoViewHolder import com.lukouguoji.gjc.holder.AssembleInfoViewHolder
import com.lukouguoji.gjc.holder.AssemblePositionViewHolder import com.lukouguoji.gjc.holder.AssemblePositionViewHolder
@@ -17,10 +16,8 @@ import com.lukouguoji.module_base.impl.FlowBus
import com.lukouguoji.module_base.ktx.launchCollect import com.lukouguoji.module_base.ktx.launchCollect
import com.lukouguoji.module_base.ktx.launchLoadingCollect 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.toJson
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 com.lukouguoji.module_base.util.Common
import com.lukouguoji.module_base.util.DictUtils import com.lukouguoji.module_base.util.DictUtils
import dev.utils.app.info.KeyValue import dev.utils.app.info.KeyValue
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -271,9 +268,6 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
assembleWeight = previousAssembleWeight assembleWeight = previousAssembleWeight
operator = previousOperator // 从operator LiveData获取的值 operator = previousOperator // 从operator LiveData获取的值
} }
// 按该运单航班号前两位(承运人)重新加载板型选项,覆盖下拉数据源
loadBoardTypeList(selectedWaybill.fno.trim().take(2))
} }
// 刷新列表 // 刷新列表
@@ -419,35 +413,22 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
/** /**
* 加载板型选项列表 * 加载板型选项列表
* @param carrier 承运人二字码(待组装运单航班号前两位);进入页面时不传,选中运单后按承运人重新加载并覆盖数据源 * @param carrier 承运人二字码(ULD 编号后两位);进入页面时不传取全量ULD 信息查询成功后按承运人重新加载并覆盖数据源
*/ */
fun loadBoardTypeList(carrier: String? = null) { fun loadBoardTypeList(carrier: String? = null) {
DictUtils.getBoardTypeList(carrier) { boardTypeList.value = it } DictUtils.getBoardTypeList(carrier) { boardTypeList.value = it }
} }
/** /**
* 板型下拉图标点击:弹出选项列表,选中后回填到板型输入框(回填后仍可手动修改) * 板型下拉选中回调:回填到板型输入框(回填后仍可手动修改)
* 下拉列表由 Activity 以锚定在输入框下方的 ListPopupWindow 弹出(外观与 BUP 的 Spinner 一致)
*/ */
fun onBoardTypeSelectClick() { fun onBoardTypeSelected(position: Int) {
val list = boardTypeList.value ?: emptyList() val list = boardTypeList.value ?: emptyList()
if (list.isEmpty()) {
showToast("暂无板型选项,请手动输入")
return
}
val jsonArray = JSONArray.parseArray(
list.map { mapOf("name" to it.key, "code" to it.value) }.toJson(false)
)
Common.singleSelect(
getTopActivity(),
"选择板型",
jsonArray,
uldInfo.value?.boardType
) { position, _ ->
uldInfo.value = uldInfo.value?.apply { uldInfo.value = uldInfo.value?.apply {
boardType = list.getOrNull(position)?.value ?: "" boardType = list.getOrNull(position)?.value ?: ""
} }
} }
}
/** /**
* ULD编号输入完成时调用 * ULD编号输入完成时调用
@@ -489,6 +470,10 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
if (!uldBean.bupFlag.isNullOrEmpty()) bupFlag = uldBean.bupFlag if (!uldBean.bupFlag.isNullOrEmpty()) bupFlag = uldBean.bupFlag
} }
// 按 ULD 编号后两位(承运人二字码)重新加载板型选项,覆盖下拉数据源
val carrier = uldNo.trim().takeLast(2)
if (carrier.length == 2) loadBoardTypeList(carrier)
// 【新增】从ULD信息提取航班信息 // 【新增】从ULD信息提取航班信息
if (uldBean.fno.isNotEmpty() && uldBean.fdate.isNotEmpty()) { if (uldBean.fno.isNotEmpty() && uldBean.fdate.isNotEmpty()) {
assembleFlightNo.value = uldBean.fno assembleFlightNo.value = uldBean.fno

View File

@@ -319,7 +319,6 @@
enable="@{true}" enable="@{true}"
hint='@{"请输入或选择"}' hint='@{"请输入或选择"}'
required="@{false}" required="@{false}"
setOnIconClickListener="@{(v) -> viewModel.onBoardTypeSelectClick()}"
setTextAllCaps="@{true}" setTextAllCaps="@{true}"
title='@{"板型:"}' title='@{"板型:"}'
titleLength="@{5}" titleLength="@{5}"
@@ -330,6 +329,7 @@
android:layout_weight="1" /> android:layout_weight="1" />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew <com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:id="@+id/bupFlagInput"
enable="@{true}" enable="@{true}"
list="@{viewModel.bupFlagList}" list="@{viewModel.bupFlagList}"
required="@{false}" required="@{false}"