feat: 国际出港开始组装新增 IMP代码、板型、BUP 输入项

- ULD 信息卡新增第二行:IMP代码(大写过滤)、板型(手输 + 下拉选择,箭头与 Spinner 同源)、BUP(否/是,默认否)
- 装货/卸货提交时 dgrCode、boardType、bupFlag 同时写入顶层参数与 useInfo,输入 ULD 后从 getUld 回填
- 板型选项走通用字典接口,字典 code 暂定 BOARDTYPE,测试环境返回为空时提示手动输入

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-09-09 10:40:43 +08:00
parent ea83361102
commit 2ba70d1a09
8 changed files with 154 additions and 4 deletions

View File

@@ -51,6 +51,7 @@ class GjcUldUseBean : Serializable {
var uldFlag: String = "" // uld分类 var uldFlag: String = "" // uld分类
var status: String = "" // uld状态0正常1故障 var status: String = "" // uld状态0正常1故障
var dgrCode: String = "" // IMP代码 var dgrCode: String = "" // IMP代码
var bupFlag: String = "" // BUP选项01
var height: String = "" // 高度 var height: String = "" // 高度
var passageway: String = "" // 通道号 var passageway: String = "" // 通道号
var passagewayId: String = "" var passagewayId: String = ""

View File

@@ -13,4 +13,7 @@ class UldInfoBean {
var totalWeight: String = "" // 总重量 var totalWeight: String = "" // 总重量
var status: String = "" // 状态(旧字段,保留兼容) var status: String = "" // 状态(旧字段,保留兼容)
var useId: Long? = null // ULD使用ID来自getUld接口 var useId: Long? = null // ULD使用ID来自getUld接口
var dgrCode: String = "" // IMP代码
var boardType: String = "" // 板型(可下拉选择,也可手动输入)
var bupFlag: String = "0" // BUP选项01默认否
} }

View File

@@ -666,7 +666,8 @@ interface Api {
* 国际出港组装 - 根据全ULD查询ULD状态和耗材重量 * 国际出港组装 - 根据全ULD查询ULD状态和耗材重量
* 接口路径: /IntExpAssemble/getUld * 接口路径: /IntExpAssemble/getUld
* @param uld ULD编号 * @param uld ULD编号
* @return ULD信息包含status0正常1故障consumeWeight耗材重量 * @return ULD信息包含status0正常1故障consumeWeight耗材重量
* dgrCodeIMP代码、boardType板型、bupFlagBUP选项 01
*/ */
@GET("IntExpAssemble/getUld") @GET("IntExpAssemble/getUld")
suspend fun getUldWithConsumeWeight(@Query("uld") uld: String): BaseResultBean<GjcUldUseBean> suspend fun getUldWithConsumeWeight(@Query("uld") uld: String): BaseResultBean<GjcUldUseBean>
@@ -675,7 +676,8 @@ interface Api {
* 国际出港组装 - 卸货 * 国际出港组装 - 卸货
* 接口路径: /IntExpAssemble/drop * 接口路径: /IntExpAssemble/drop
* @param data 请求参数abPc组装件数、abWeight组装重量、consumeWeight耗材重量 * @param data 请求参数abPc组装件数、abWeight组装重量、consumeWeight耗材重量
* ldId组装人、loadArea组装区、useInfoULD信息、wbInfo运单信息、userId用户ID * ldId组装人、loadArea组装区、useInfoULD信息、wbInfo运单信息、userId用户ID
* dgrCodeIMP代码、boardType板型、bupFlagBUP选项 01
*/ */
@POST("IntExpAssemble/drop") @POST("IntExpAssemble/drop")
suspend fun assembleDropCargo(@Body data: RequestBody): BaseResultBean<GjcWarehouse> suspend fun assembleDropCargo(@Body data: RequestBody): BaseResultBean<GjcWarehouse>
@@ -684,7 +686,8 @@ interface Api {
* 国际出港组装 - 装货 * 国际出港组装 - 装货
* 接口路径: /IntExpAssemble/assemble * 接口路径: /IntExpAssemble/assemble
* @param data 请求参数abPc组装件数、abWeight组装重量、consumeWeight耗材重量 * @param data 请求参数abPc组装件数、abWeight组装重量、consumeWeight耗材重量
* ldId组装人、loadArea组装区、useInfoULD信息、wbInfo运单信息、userId用户ID * ldId组装人、loadArea组装区、useInfoULD信息、wbInfo运单信息、userId用户ID
* dgrCodeIMP代码、boardType板型、bupFlagBUP选项 01
*/ */
@POST("IntExpAssemble/assemble") @POST("IntExpAssemble/assemble")
suspend fun assembleLoadCargo(@Body data: RequestBody): BaseResultBean<GjcWarehouse> suspend fun assembleLoadCargo(@Body data: RequestBody): BaseResultBean<GjcWarehouse>

View File

@@ -625,6 +625,21 @@ object DictUtils {
} }
} }
/**
* 板型列表(国际出港组装-开始组装)
* 字典 codeBOARDTYPE显示与提交均使用 value 字段
*/
fun getBoardTypeList(callBack: (List<KeyValue>) -> Unit) {
launchCollect({
NetApply.api
.getDictList("BOARDTYPE")
}) {
onSuccess = {
callBack((it.data ?: emptyList()).map { b -> KeyValue(b.value, b.value) })
}
}
}
// 报文类型 // 报文类型
fun getTelegramTypeList(callBack: (List<KeyValue>) -> Unit) { fun getTelegramTypeList(callBack: (List<KeyValue>) -> Unit) {
launchCollect({ launchCollect({

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 输入框边框 + 与 Spinnerbg_spinner_pda_new完全一致的下拉箭头用于“手动输入 + 下拉选择”组合输入框 -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_data_layout_new" />
<item
android:width="8.7dp"
android:height="6dp"
android:drawable="@drawable/img_sp_down"
android:gravity="center_vertical|right"
android:right="10dp" />
</layer-list>

View File

@@ -4,6 +4,7 @@ import android.app.Activity
import android.content.Context 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 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
@@ -66,8 +67,17 @@ class IntExpAssembleStartActivity :
setBackArrow("国际出港开始组装") setBackArrow("国际出港开始组装")
binding.viewModel = viewModel binding.viewModel = viewModel
// 为ULD编号添加大写字母和数字的输入限制 // 为ULD编号、IMP代码添加大写字母和数字的输入限制
binding.uldNoInput.et.setUpperCaseAlphanumericFilter() binding.uldNoInput.et.setUpperCaseAlphanumericFilter()
binding.impCodeInput.et.setUpperCaseAlphanumericFilter()
// 板型:手动输入 + 下拉选择组合框。箭头复用 Spinner 同款背景绘制(同资源、同尺寸、同边距),
// 图标位不放图片,仅作为覆盖在箭头上的透明点击区域(点击事件由布局 setOnIconClickListener 绑定)
binding.boardTypeInput.apply {
ll.setBackgroundResource(com.lukouguoji.module_base.R.drawable.bg_data_layout_new_dropdown)
iv.setImageDrawable(null)
iv.visibility = View.VISIBLE
}
// 初始化列表 // 初始化列表
initRecyclerViews() initRecyclerViews()
@@ -81,6 +91,9 @@ class IntExpAssembleStartActivity :
// 加载组装人列表 // 加载组装人列表
viewModel.loadAssemblerList() viewModel.loadAssemblerList()
// 加载板型选项列表
viewModel.loadBoardTypeList()
// 监听登出事件,清空缓存 // 监听登出事件,清空缓存
FlowBus.with<Any>(ConstantEvent.LOGOUT).observe(this) { FlowBus.with<Any>(ConstantEvent.LOGOUT).observe(this) {
viewModel.clearCachedOperator() viewModel.clearCachedOperator()

View File

@@ -2,6 +2,7 @@ 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
@@ -16,8 +17,11 @@ 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 dev.utils.app.info.KeyValue import dev.utils.app.info.KeyValue
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -75,6 +79,12 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
// ========== 组装人列表 ========== // ========== 组装人列表 ==========
val assemblerList = MutableLiveData<List<KeyValue>>(emptyList()) val assemblerList = MutableLiveData<List<KeyValue>>(emptyList())
// ========== BUP选项01默认否 ==========
val bupFlagList = listOf(KeyValue("", "0"), KeyValue("", "1"))
// ========== 板型选项(字典;支持下拉选择,也支持手动输入)==========
val boardTypeList = MutableLiveData<List<KeyValue>>(emptyList())
// ========== 标记位,避免重复查询 ========== // ========== 标记位,避免重复查询 ==========
private var lastQueriedUldNo = "" private var lastQueriedUldNo = ""
@@ -404,6 +414,37 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
} }
/**
* 加载板型选项列表(字典)
*/
fun loadBoardTypeList() {
DictUtils.getBoardTypeList { boardTypeList.value = it }
}
/**
* 板型下拉图标点击:弹出选项列表,选中后回填到板型输入框(回填后仍可手动修改)
*/
fun onBoardTypeSelectClick() {
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 {
boardType = list.getOrNull(position)?.value ?: ""
}
}
}
/** /**
* ULD编号输入完成时调用 * ULD编号输入完成时调用
*/ */
@@ -438,6 +479,10 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
} }
// 保存useId用于装货/卸货接口) // 保存useId用于装货/卸货接口)
useId = uldBean.useId useId = uldBean.useId
// 回填 IMP代码 / 板型 / BUP服务端有值时覆盖修改模式回显为空时保留当前输入
if (!uldBean.dgrCode.isNullOrEmpty()) dgrCode = uldBean.dgrCode
if (!uldBean.boardType.isNullOrEmpty()) boardType = uldBean.boardType
if (!uldBean.bupFlag.isNullOrEmpty()) bupFlag = uldBean.bupFlag
} }
// 【新增】从ULD信息提取航班信息 // 【新增】从ULD信息提取航班信息
@@ -606,9 +651,17 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
val loadAreaId = selectedPosition.value?.positionCode?.trim() ?: "" val loadAreaId = selectedPosition.value?.positionCode?.trim() ?: ""
// IMP代码 / 板型 / BUP接口新增字段useInfo 与顶层参数均需携带)
val dgrCode = uldInfo.value?.dgrCode?.trim() ?: ""
val boardType = uldInfo.value?.boardType?.trim() ?: ""
val bupFlag = uldInfo.value?.bupFlag?.ifEmpty { "0" } ?: "0"
// 2. 构建useInfoULD信息 // 2. 构建useInfoULD信息
val useInfo = mapOf( val useInfo = mapOf(
"uld" to uldNo, "uld" to uldNo,
"dgrCode" to dgrCode.ifEmpty { null },
"boardType" to boardType.ifEmpty { null },
"bupFlag" to bupFlag,
"consumeWeight" to materialWeight.toDoubleOrNull(), "consumeWeight" to materialWeight.toDoubleOrNull(),
"status" to when (uldInfo.value?.uldStatus) { "status" to when (uldInfo.value?.uldStatus) {
"正常" -> "0" "正常" -> "0"
@@ -693,6 +746,9 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
"ldId" to operatorValue, "ldId" to operatorValue,
"loadArea" to loadArea, "loadArea" to loadArea,
"loadAreaId" to loadAreaId.ifEmpty { null }, // 组装位置ID "loadAreaId" to loadAreaId.ifEmpty { null }, // 组装位置ID
"dgrCode" to dgrCode.ifEmpty { null }, // IMP代码
"boardType" to boardType.ifEmpty { null }, // 板型
"bupFlag" to bupFlag, // BUP选项01
"useInfo" to useInfo, "useInfo" to useInfo,
"wbInfo" to wbInfo, "wbInfo" to wbInfo,
"userId" to SharedPreferenceUtil.getString(Constant.Share.account) "userId" to SharedPreferenceUtil.getString(Constant.Share.account)

View File

@@ -293,6 +293,54 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" /> android:layout_weight="1" />
</LinearLayout> </LinearLayout>
<!-- 第二行IMP代码、板型下拉选择 + 手动输入、BUP -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:id="@+id/impCodeInput"
enable="@{true}"
hint='@{"请输入IMP代码"}'
required="@{false}"
title='@{"IMP代码"}'
titleLength="@{5}"
type="@{DataLayoutType.INPUT}"
value="@={viewModel.uldInfo.dgrCode}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:id="@+id/boardTypeInput"
enable="@{true}"
hint='@{"请输入或选择"}'
required="@{false}"
setOnIconClickListener="@{(v) -> viewModel.onBoardTypeSelectClick()}"
setTextAllCaps="@{true}"
title='@{"板型:"}'
titleLength="@{5}"
type="@{DataLayoutType.INPUT}"
value="@={viewModel.uldInfo.boardType}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
enable="@{true}"
list="@{viewModel.bupFlagList}"
required="@{false}"
title='@{"BUP"}'
titleLength="@{5}"
type="@{DataLayoutType.SPINNER}"
value="@={viewModel.uldInfo.bupFlag}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout> </LinearLayout>
<!-- 运单信息卡片 --> <!-- 运单信息卡片 -->