feat: 开始组装 opt

This commit is contained in:
2025-12-19 11:42:21 +08:00
parent b8fbc304f1
commit c6fe8f5310
5 changed files with 280 additions and 266 deletions

View File

@@ -39,6 +39,9 @@ class AssembleInfoBean {
// 原始运单数据(用于同步更新和填充表单) // 原始运单数据(用于同步更新和填充表单)
var waybillData: AssembleWaybillBean? = null var waybillData: AssembleWaybillBean? = null
// 关联的原始数据用于存储GjcUldUseBean等对象
var tag: Any? = null
// ========== 视觉样式字段 ========== // ========== 视觉样式字段 ==========
var hasArrow: Boolean = false // 是否显示箭头一级ULD行为true var hasArrow: Boolean = false // 是否显示箭头一级ULD行为true
var isOrange: Boolean = false // 是否橙色文字(暂保留) var isOrange: Boolean = false // 是否橙色文字(暂保留)

View File

@@ -0,0 +1,10 @@
package com.lukouguoji.module_base.bean
/**
* 国际出港组装记录Bean
* 对应API: /IntExpAssemble/queryAssembled
*/
class GjcAssembled {
var uldUse: GjcUldUseBean? = null // ULD信息
var warehouseList: MutableList<GjcWarehouse>? = null // 运单列表
}

View File

@@ -22,6 +22,7 @@ import com.lukouguoji.module_base.bean.FlightBean
import com.lukouguoji.module_base.bean.FlightFilterBean import com.lukouguoji.module_base.bean.FlightFilterBean
import com.lukouguoji.module_base.bean.GbCarOrUldBean import com.lukouguoji.module_base.bean.GbCarOrUldBean
import com.lukouguoji.module_base.bean.GjcAssembleAllocate import com.lukouguoji.module_base.bean.GjcAssembleAllocate
import com.lukouguoji.module_base.bean.GjcAssembled
import com.lukouguoji.module_base.bean.GjcBoxAddInsertBean import com.lukouguoji.module_base.bean.GjcBoxAddInsertBean
import com.lukouguoji.module_base.bean.GjcBoxAssembleBean import com.lukouguoji.module_base.bean.GjcBoxAssembleBean
import com.lukouguoji.module_base.bean.GjcBoxDetailsBean import com.lukouguoji.module_base.bean.GjcBoxDetailsBean
@@ -628,6 +629,25 @@ interface Api {
@POST("IntExpAssemble/assemble") @POST("IntExpAssemble/assemble")
suspend fun assembleLoadCargo(@Body data: RequestBody): BaseResultBean<GjcWarehouse> suspend fun assembleLoadCargo(@Body data: RequestBody): BaseResultBean<GjcWarehouse>
/**
* 国际出港组装 - 查询已组装的ULD列表
* 接口路径: /IntExpAssemble/queryAssembled
* @param data 请求参数fno航班号必填、fdate航班日期必填
* loadArea组装位置必填、uldULD编号可选
* @return 返回已组装的ULD列表包含ULD信息和运单列表
*/
@POST("IntExpAssemble/queryAssembled")
suspend fun getAssembledList(@Body data: RequestBody): BaseResultBean<List<GjcAssembled>>
/**
* 国际出港组装 - 根据ULD查询已组装的运单列表
* 接口路径: /IntExpAssemble/queryAssembledByUld
* @param data 请求参数GjcUldUseBean对象包含useId、uld等信息
* @return 返回该ULD下的运单列表
*/
@POST("IntExpAssemble/queryAssembledByUld")
suspend fun getAssembledWaybillsByUld(@Body data: RequestBody): BaseResultBean<List<GjcWarehouse>>
/** /**
* 国际出港出库交接-分页查询 * 国际出港出库交接-分页查询
* 接口路径: /IntExpOutHandover/pageQuery * 接口路径: /IntExpOutHandover/pageQuery

View File

@@ -24,6 +24,14 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
// ========== 搜索条件 ========== // ========== 搜索条件 ==========
val searchText = MutableLiveData("") val searchText = MutableLiveData("")
val uldSearchText = MutableLiveData("") // ULD搜索框
// ========== 组装参数(从选中运单自动提取)==========
val assembleFlightNo = MutableLiveData("") // 航班号
val assembleFlightDate = MutableLiveData("") // 航班日期
// ========== 防抖标记 ==========
private var lastQueriedAssembledParams = "" // 避免重复查询
// ========== 左侧组装信息列表 ========== // ========== 左侧组装信息列表 ==========
val assembleInfoList = MutableLiveData<MutableList<AssembleInfoBean>>() val assembleInfoList = MutableLiveData<MutableList<AssembleInfoBean>>()
@@ -55,27 +63,6 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
// ========== 标记位,避免重复查询 ========== // ========== 标记位,避免重复查询 ==========
private var lastQueriedUldNo = "" private var lastQueriedUldNo = ""
// ========== 本地存储(页面生命周期内)==========
/**
* 已组装货物的本地存储
* Key: ULD编号
* Value: 该ULD下的运单列表
*/
private val assembledCargoMap = mutableMapOf<String, MutableList<AssembleWaybillBean>>()
/**
* 扁平化的组装信息列表(包含一级和二级行)
* 用于RecyclerView显示
*/
private val flatAssembleInfoList = mutableListOf<AssembleInfoBean>()
/**
* 编辑模式标记
* null: 新增模式
* 非null: 编辑模式存储原始ULD编号和运单号
*/
private var editMode: Pair<String, String>? = null // Pair<ULD编号, 运单号>
/** /**
* ULD编号锁定状态 * ULD编号锁定状态
*/ */
@@ -122,6 +109,9 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
// 刷新列表 // 刷新列表
assemblePositionList.value = list assemblePositionList.value = list
// 触发组装信息列表查询
loadAssembledList()
} }
/** /**
@@ -143,6 +133,10 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
if (selectedWaybill != null) { if (selectedWaybill != null) {
selectedWaybill.isSelected.set(true) selectedWaybill.isSelected.set(true)
// 自动提取航班号和航班日期
assembleFlightNo.value = selectedWaybill.fno
assembleFlightDate.value = selectedWaybill.fdate
// 保存当前的组装人(始终保留) // 保存当前的组装人(始终保留)
val previousOperator = waybillInfo.value?.operator ?: "" val previousOperator = waybillInfo.value?.operator ?: ""
@@ -155,11 +149,8 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
previousAssembleCount = "" previousAssembleCount = ""
previousAssembleWeight = "" previousAssembleWeight = ""
// 如果在编辑模式,退出编辑模式并解锁 ULD // 解锁ULD编号
if (editMode != null) {
editMode = null
isUldNoLocked.value = false isUldNoLocked.value = false
}
} else { } else {
// 同一个运单:保留组装件数和组装重量 // 同一个运单:保留组装件数和组装重量
previousAssembleCount = waybillInfo.value?.assembleCount ?: "" previousAssembleCount = waybillInfo.value?.assembleCount ?: ""
@@ -179,6 +170,12 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
// 刷新列表 // 刷新列表
waybillList.value = list waybillList.value = list
// 清除防抖标记,强制重新查询组装信息列表
lastQueriedAssembledParams = ""
// 触发组装信息列表查询
loadAssembledList()
} }
/** /**
@@ -226,14 +223,11 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
if (currentWaybillNo.isNotEmpty()) { if (currentWaybillNo.isNotEmpty()) {
val existsInNewList = waybillBeanList.any { it.waybillNo == currentWaybillNo } val existsInNewList = waybillBeanList.any { it.waybillNo == currentWaybillNo }
if (!existsInNewList) { if (!existsInNewList) {
// 当前运单不在新列表中,清空表单并退出编辑模式 // 当前运单不在新列表中,清空表单
val previousOperator = waybillInfo.value?.operator ?: "" val previousOperator = waybillInfo.value?.operator ?: ""
waybillInfo.value = WaybillInfoBean().apply { waybillInfo.value = WaybillInfoBean().apply {
operator = previousOperator operator = previousOperator
} }
if (editMode != null) {
editMode = null
}
} }
} }
@@ -278,14 +272,11 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
if (currentWaybillNo.isNotEmpty()) { if (currentWaybillNo.isNotEmpty()) {
val existsInNewList = waybillBeanList.any { it.waybillNo == currentWaybillNo } val existsInNewList = waybillBeanList.any { it.waybillNo == currentWaybillNo }
if (!existsInNewList) { if (!existsInNewList) {
// 当前运单不在新列表中,清空表单并退出编辑模式 // 当前运单不在新列表中,清空表单
val previousOperator = waybillInfo.value?.operator ?: "" val previousOperator = waybillInfo.value?.operator ?: ""
waybillInfo.value = WaybillInfoBean().apply { waybillInfo.value = WaybillInfoBean().apply {
operator = previousOperator operator = previousOperator
} }
if (editMode != null) {
editMode = null
}
} }
} }
@@ -429,35 +420,18 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
} }
// 2. 获取或构建运单Bean // 2. 获取或构建运单Bean
val selectedWaybill: AssembleWaybillBean = if (editMode != null) { // 从运单列表中获取选中的运单
// 编辑模式:从本地存储中获取运单数据
val uldNoInEdit = editMode!!.first
val waybillNoInEdit = editMode!!.second
val storedList = assembledCargoMap[uldNoInEdit]
val storedWaybill = storedList?.firstOrNull { it.waybillNo == waybillNoInEdit }
if (storedWaybill == null) {
showToast("未找到运单数据")
return
}
// 使用存储的运单数据(包含原始件数/重量和其他字段)
storedWaybill
} else {
// 新增模式:从运单列表中获取选中的运单
val currentWaybillList = waybillList.value val currentWaybillList = waybillList.value
if (currentWaybillList == null) { if (currentWaybillList == null) {
showToast("运单列表为空") showToast("运单列表为空")
return return
} }
val selected = currentWaybillList.firstOrNull { it.isSelected.get() } val selectedWaybill = currentWaybillList.firstOrNull { it.isSelected.get() }
if (selected == null) { if (selectedWaybill == null) {
showToast("请选择运单") showToast("请选择运单")
return return
} }
selected
}
// 3. 构建useInfoULD信息 // 3. 构建useInfoULD信息
val useInfo = mapOf( val useInfo = mapOf(
@@ -472,13 +446,13 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
) )
// 4. 构建wbInfo运单信息 // 4. 构建wbInfo运单信息
// 如果是编辑模式,使用原始运单件数/重量否则使用当前件数/重量 // 使用原始运单件数/重量(如果有),否则使用当前件数/重量
val waybillPc = if (editMode != null && selectedWaybill.originalPieces.isNotEmpty()) { val waybillPc = if (selectedWaybill.originalPieces.isNotEmpty()) {
selectedWaybill.originalPieces.toLongOrNull() selectedWaybill.originalPieces.toLongOrNull()
} else { } else {
selectedWaybill.pieces.toLongOrNull() selectedWaybill.pieces.toLongOrNull()
} }
val waybillWeight = if (editMode != null && selectedWaybill.originalWeight.isNotEmpty()) { val waybillWeight = if (selectedWaybill.originalWeight.isNotEmpty()) {
selectedWaybill.originalWeight.toDoubleOrNull() selectedWaybill.originalWeight.toDoubleOrNull()
} else { } else {
selectedWaybill.weight.toDoubleOrNull() selectedWaybill.weight.toDoubleOrNull()
@@ -505,12 +479,9 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
"userId" to SharedPreferenceUtil.getString(Constant.Share.account) "userId" to SharedPreferenceUtil.getString(Constant.Share.account)
).toRequestBody() ).toRequestBody()
// 6. 立即同步到组装信息列表(不等接口成功 // 6. 调用接口带Loading等待接口返回
val operationName = if (isLoad) "装货" else "卸货" val operationName = if (isLoad) "装货" else "卸货"
handleOperationSuccess(operationName, isLoad, uldNo, selectedWaybill, assembleCount, assembleWeight) launchLoadingCollect({
// 7. 调用接口后台执行不阻塞UI
launchCollect({
if (isLoad) { if (isLoad) {
NetApply.api.assembleLoadCargo(params) NetApply.api.assembleLoadCargo(params)
} else { } else {
@@ -518,10 +489,11 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
} }
}) { }) {
onSuccess = { result -> onSuccess = { result ->
// 接口成功,无需额外操作(已经同步到本地) // 接口成功后才显示成功提示并刷新列表
handleOperationSuccess(operationName, isLoad, uldNo, selectedWaybill, assembleCount, assembleWeight)
} }
onFailed = { code, message -> onFailed = { code, message ->
showToast("${operationName}接口调用失败: $message(数据已保存到本地)") showToast("${operationName}失败: $message")
} }
} }
} }
@@ -539,37 +511,8 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
) { ) {
showToast("${operationName}成功") showToast("${operationName}成功")
// 创建一个包含本次操作件数和重量的运单Bean // 重新查询组装信息列表(刷新数据)
val assembleWaybill = AssembleWaybillBean() loadAssembledList()
assembleWaybill.waybillNo = selectedWaybill.waybillNo
assembleWaybill.pieces = assembleCount // 本次操作的件数
assembleWaybill.weight = assembleWeight // 本次操作的重量
assembleWaybill.flight = selectedWaybill.flight
assembleWaybill.fno = selectedWaybill.fno
assembleWaybill.fdate = selectedWaybill.fdate
assembleWaybill.whId = selectedWaybill.whId
assembleWaybill.isMarked = selectedWaybill.isMarked
// 保存原始运单件数/重量(用于编辑模式回显)
assembleWaybill.originalPieces = selectedWaybill.originalPieces.ifEmpty { selectedWaybill.pieces }
assembleWaybill.originalWeight = selectedWaybill.originalWeight.ifEmpty { selectedWaybill.weight }
// 判断是新增还是编辑模式
if (editMode != null) {
// 编辑模式:更新本地存储中的对应运单
updateAssembledCargoInLocal(
uldNo = editMode!!.first,
oldWaybillNo = editMode!!.second,
newWaybillBean = assembleWaybill,
isLoad = isLoad
)
} else {
// 新增模式:添加到本地存储
addAssembledCargoToLocal(uldNo, assembleWaybill, isLoad)
}
// 同步刷新组装信息列表
syncAssembleInfoListFromLocal()
// 刷新运单列表 // 刷新运单列表
loadInitialWaitingAssemble() loadInitialWaitingAssemble()
@@ -578,96 +521,30 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
clearForm() clearForm()
} }
/**
* 从本地存储同步组装信息列表
* 1. 遍历 assembledCargoMap为每个 ULD 生成一级行
* 2. 计算总件数/总重量(求和子运单)
* 3. 根据展开状态决定是否添加二级运单行
* 4. 更新 LiveData 触发 UI 刷新
*/
private fun syncAssembleInfoListFromLocal() {
// 记录当前展开状态(避免刷新后展开状态丢失)
val expandedUlds = flatAssembleInfoList
.filter { it.itemType == AssembleInfoBean.ItemType.ULD_HEADER && it.isExpanded.get() }
.map { it.uldNo }
.toSet()
flatAssembleInfoList.clear()
// 遍历每个 ULD带序号
var uldIndex = 1
assembledCargoMap.forEach { (uldNo, waybillList) ->
// 计算总件数和总重量
var totalPieces = 0
var totalWeight = 0.0
waybillList.forEach { waybill ->
totalPieces += waybill.pieces.toIntOrNull() ?: 0
totalWeight += waybill.weight.toDoubleOrNull() ?: 0.0
}
// 创建一级 ULD 行
val uldHeader = AssembleInfoBean().apply {
itemType = AssembleInfoBean.ItemType.ULD_HEADER
this.uldNo = uldNo
this.uldIndex = uldIndex
this.totalPieces = totalPieces
this.totalWeight = totalWeight
hasArrow = true
showIndex = true // 显示序号
// 恢复展开状态
isExpanded.set(expandedUlds.contains(uldNo))
// 保存子运单(用于展开/折叠)
waybillChildren = waybillList.map { waybill ->
AssembleInfoBean().apply {
itemType = AssembleInfoBean.ItemType.WAYBILL_DETAIL
parentUldNo = uldNo
wbNo = waybill.waybillNo
waybillPieces = waybill.pieces.toIntOrNull() ?: 0
waybillWeight = waybill.weight.toDoubleOrNull() ?: 0.0
waybillData = waybill
showIndent = true
showIndex = false
}
}.toMutableList()
}
// 添加一级行
flatAssembleInfoList.add(uldHeader)
// 如果展开,添加二级运单行
if (uldHeader.isExpanded.get()) {
flatAssembleInfoList.addAll(uldHeader.waybillChildren)
}
// 递增序号
uldIndex++
}
// 更新 LiveData
assembleInfoList.value = flatAssembleInfoList.toMutableList()
}
/** /**
* 组装信息列表点击事件 * 组装信息列表点击事件
* 1. 点击一级 ULD 行:切换展开/折叠状态 * 1. 点击一级ULD行展开/折叠(按需加载运单列表)
* 2. 点击二级运单行:进入编辑模式,填充表单 * 2. 点击二级运单行:填充表单(编辑模式)
*/ */
fun onAssembleInfoItemClick(position: Int) { fun onAssembleInfoItemClick(position: Int) {
val list = flatAssembleInfoList val list = assembleInfoList.value ?: return
if (position !in list.indices) return if (position !in list.indices) return
val clickedItem = list[position] val clickedItem = list[position]
when (clickedItem.itemType) { when (clickedItem.itemType) {
AssembleInfoBean.ItemType.ULD_HEADER -> { AssembleInfoBean.ItemType.ULD_HEADER -> {
// 一级 ULD 行:切换展开/折叠 // 一级ULD行切换展开/折叠
val newExpandState = !clickedItem.isExpanded.get() val newExpandState = !clickedItem.isExpanded.get()
clickedItem.isExpanded.set(newExpandState) clickedItem.isExpanded.set(newExpandState)
// 重新生成扁平化列表 if (newExpandState) {
syncAssembleInfoListFromLocal() // 展开查询该ULD的运单列表
loadWaybillsByUld(position, clickedItem)
} else {
// 折叠:移除二级运单行
removeWaybillRows(position)
}
} }
AssembleInfoBean.ItemType.WAYBILL_DETAIL -> { AssembleInfoBean.ItemType.WAYBILL_DETAIL -> {
@@ -677,20 +554,111 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
} }
} }
/**
* 加载指定ULD的运单列表
*/
private fun loadWaybillsByUld(uldPosition: Int, uldItem: AssembleInfoBean) {
val uldBean = uldItem.tag as? GjcUldUseBean ?: return
// 检查是否已缓存
if (uldBean.waybillDetails != null) {
// 已缓存,直接展开
insertWaybillRows(uldPosition, uldBean.waybillDetails!!)
return
}
// 未缓存,调用接口查询
val params = uldBean.toRequestBody()
launchLoadingCollect({ NetApply.api.getAssembledWaybillsByUld(params) }) {
onSuccess = { result ->
val waybillList = result.data ?: emptyList()
if (waybillList.isEmpty()) {
showToast("该ULD暂无运单记录")
// 折叠回去
uldItem.isExpanded.set(false)
} else {
// 缓存到GjcUldUseBean
uldBean.waybillDetails = waybillList.toMutableList()
// 插入二级运单行
insertWaybillRows(uldPosition, waybillList)
}
}
onFailed = { code, message ->
showToast("查询失败: $message")
// 折叠回去
uldItem.isExpanded.set(false)
}
}
}
/**
* 在指定位置后插入二级运单行
*/
private fun insertWaybillRows(uldPosition: Int, waybillList: List<GjcWarehouse>) {
val list = assembleInfoList.value?.toMutableList() ?: return
val uldItem = list[uldPosition]
// 生成二级运单行
val waybillRows = waybillList.map { warehouse ->
AssembleInfoBean().apply {
itemType = AssembleInfoBean.ItemType.WAYBILL_DETAIL
parentUldNo = uldItem.uldNo
wbNo = warehouse.wbNo
waybillPieces = warehouse.pc.toInt()
waybillWeight = warehouse.weight
showIndent = true
showIndex = false
// 转换为AssembleWaybillBean用于填充表单
waybillData = AssembleWaybillBean().apply {
waybillNo = warehouse.wbNo
pieces = warehouse.pc.toString()
weight = String.format("%.1f", warehouse.weight)
flight = warehouse.flight
fno = warehouse.fno
fdate = warehouse.fdate
whId = warehouse.whId
}
}
}
// 插入到ULD行后面
list.addAll(uldPosition + 1, waybillRows)
assembleInfoList.value = list
}
/**
* 移除指定ULD后的二级运单行
*/
private fun removeWaybillRows(uldPosition: Int) {
val list = assembleInfoList.value?.toMutableList() ?: return
val uldItem = list[uldPosition]
// 移除该ULD的所有二级行
list.removeAll {
it.itemType == AssembleInfoBean.ItemType.WAYBILL_DETAIL &&
it.parentUldNo == uldItem.uldNo
}
assembleInfoList.value = list
}
/** /**
* 从二级运单行填充表单(编辑模式) * 从二级运单行填充表单(编辑模式)
* 1. 填充 ULD 信息(并锁定 ULD 编号) * 1. 填充ULD信息并锁定ULD编号
* 2. 填充运单信息(使用原始运单件数/重量,只读) * 2. 填充运单信息(使用原始运单件数/重量,只读)
* 3. 保留组装件数、组装重量、组装人为可编辑 * 3. 保留组装件数、组装重量、组装人为可编辑
* 4. 标记编辑模式
*/ */
private fun fillFormFromWaybillDetail(item: AssembleInfoBean) { private fun fillFormFromWaybillDetail(item: AssembleInfoBean) {
val waybill = item.waybillData ?: return val waybill = item.waybillData ?: return
// 1. 填充 ULD 信息 // 1. 填充ULD信息
uldInfo.value = uldInfo.value?.apply { uldInfo.value = uldInfo.value?.apply {
uldNo = item.parentUldNo uldNo = item.parentUldNo
// 耗材重量、ULD 状态保持不变 // 耗材重量、ULD状态保持不变
} }
// 保存当前的组装人(在创建新对象前) // 保存当前的组装人(在创建新对象前)
@@ -707,109 +675,121 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
operator = previousOperator // 保留之前选择的组装人 operator = previousOperator // 保留之前选择的组装人
} }
// 3. 锁定 ULD 编号 // 3. 锁定ULD编号
isUldNoLocked.value = true isUldNoLocked.value = true
// 4. 标记编辑模式(存储原始 ULD 编号和运单号 // 4. 查询ULD信息如果需要
editMode = Pair(item.parentUldNo, waybill.waybillNo)
// 5. 查询 ULD 信息(如果需要)
if (item.parentUldNo != lastQueriedUldNo) { if (item.parentUldNo != lastQueriedUldNo) {
lastQueriedUldNo = item.parentUldNo lastQueriedUldNo = item.parentUldNo
queryUldInfo(item.parentUldNo) queryUldInfo(item.parentUldNo)
} }
} }
/** /**
* 新增模式:添加已组装货物到本地存储 * 查询已组装的ULD列表
* @param isLoad true-装货false-卸货(减) * 参数来源:
* - fno/fdate从当前选中的运单自动提取
* - loadArea从当前选中的组装位置获取
* - uld从ULD搜索框获取可选
*/ */
private fun addAssembledCargoToLocal(uldNo: String, waybill: AssembleWaybillBean, isLoad: Boolean) { fun loadAssembledList() {
val list = assembledCargoMap.getOrPut(uldNo) { mutableListOf() } // 1. 参数验证
val fno = assembleFlightNo.value ?: ""
val fdate = assembleFlightDate.value ?: ""
val loadArea = selectedPosition.value?.positionName ?: ""
val uldSearch = uldSearchText.value ?: ""
// 检查是否已存在 // 必填参数检查
val existingIndex = list.indexOfFirst { it.waybillNo == waybill.waybillNo } if (fno.isEmpty() || fdate.isEmpty() || loadArea.isEmpty()) {
if (existingIndex >= 0) { // 参数缺失,清空列表(静默处理)
// 已存在:累加或减去件数和重量 assembleInfoList.value = mutableListOf()
val existing = list[existingIndex] return
val existingPieces = existing.pieces.toIntOrNull() ?: 0
val existingWeight = existing.weight.toDoubleOrNull() ?: 0.0
val newPieces = waybill.pieces.toIntOrNull() ?: 0
val newWeight = waybill.weight.toDoubleOrNull() ?: 0.0
if (isLoad) {
// 装货:累加
existing.pieces = (existingPieces + newPieces).toString()
existing.weight = String.format("%.1f", existingWeight + newWeight)
} else {
// 卸货:减去
val resultPieces = existingPieces - newPieces
val resultWeight = existingWeight - newWeight
if (resultPieces <= 0 || resultWeight <= 0) {
// 减到0或负数从列表中移除
list.removeAt(existingIndex)
// 如果该ULD下没有运单了删除整个ULD
if (list.isEmpty()) {
assembledCargoMap.remove(uldNo)
} }
// 2. 防抖检查(避免重复查询)
val currentParams = "$fno|$fdate|$loadArea|$uldSearch"
if (currentParams == lastQueriedAssembledParams) {
return
}
lastQueriedAssembledParams = currentParams
// 3. 构建请求参数
val params = mapOf(
"fno" to fno,
"fdate" to fdate,
"loadArea" to loadArea,
"uld" to uldSearch.ifEmpty { null } // 空值时传null
).toRequestBody()
// 4. 调用接口
launchLoadingCollect({ NetApply.api.getAssembledList(params) }) {
onSuccess = { result ->
val uldList = result.data ?: emptyList()
if (uldList.isEmpty()) {
showToast("暂无已组装记录")
assembleInfoList.value = mutableListOf()
} else { } else {
existing.pieces = resultPieces.toString() // 转换为AssembleInfoBean列表
existing.weight = String.format("%.1f", resultWeight) convertToAssembleInfoBeans(uldList)
} }
} }
} else { onFailed = { code, message ->
// 不存在:直接新增(只有装货时才会走到这里) showToast("查询失败: $message")
if (isLoad) { assembleInfoList.value = mutableListOf()
list.add(waybill)
} }
} }
} }
/** /**
* 编辑模式:更新本地存储中的运单数据 * 数据转换: List<GjcAssembled> → List<AssembleInfoBean>
* @param isLoad true-装货false-卸货(减) * 只生成一级ULD行不包含二级运单行
* 同时将运单列表缓存到uldBean.waybillDetails
*/ */
private fun updateAssembledCargoInLocal( private fun convertToAssembleInfoBeans(assembledList: List<GjcAssembled>) {
uldNo: String, val infoList = assembledList.mapIndexed { index, assembled ->
oldWaybillNo: String, val uldBean = assembled.uldUse
newWaybillBean: AssembleWaybillBean, val warehouseList = assembled.warehouseList
isLoad: Boolean
) {
val list = assembledCargoMap[uldNo] ?: return
// 查找并更新 if (uldBean == null) {
val index = list.indexOfFirst { it.waybillNo == oldWaybillNo } return@mapIndexed null
if (index >= 0) { }
val existing = list[index]
val existingPieces = existing.pieces.toIntOrNull() ?: 0
val existingWeight = existing.weight.toDoubleOrNull() ?: 0.0
val newPieces = newWaybillBean.pieces.toIntOrNull() ?: 0
val newWeight = newWaybillBean.weight.toDoubleOrNull() ?: 0.0
if (isLoad) { // 缓存运单列表到uldBean展开时不需要再次查询
// 装货:累加 if (warehouseList != null && warehouseList.isNotEmpty()) {
existing.pieces = (existingPieces + newPieces).toString() uldBean.waybillDetails = warehouseList
existing.weight = String.format("%.1f", existingWeight + newWeight) }
} else {
// 卸货:减去
val resultPieces = existingPieces - newPieces
val resultWeight = existingWeight - newWeight
if (resultPieces <= 0 || resultWeight <= 0) { // 计算总件数和总重量(从运单列表求和)
// 减到0或负数从列表中移除 val calculatedPieces = warehouseList?.sumOf { it.pc.toInt() } ?: 0
list.removeAt(index) val calculatedWeight = warehouseList?.sumOf { it.weight } ?: 0.0
// 如果该ULD下没有运单了删除整个ULD
if (list.isEmpty()) { AssembleInfoBean().apply {
assembledCargoMap.remove(uldNo) itemType = AssembleInfoBean.ItemType.ULD_HEADER
} uldNo = uldBean.uld
} else { uldIndex = index + 1
existing.pieces = resultPieces.toString()
existing.weight = String.format("%.1f", resultWeight) // 使用计算的总件数和总重量
} totalPieces = calculatedPieces
totalWeight = calculatedWeight
hasArrow = true
showIndex = true
isExpanded.set(false) // 默认折叠
// 关联原始ULD数据用于点击展开时查询
tag = uldBean // 使用tag存储GjcUldUseBean对象
} }
}.filterNotNull().toMutableList()
assembleInfoList.value = infoList
} }
/**
* ULD搜索框输入完成回调
*/
fun onUldSearchInputComplete() {
loadAssembledList()
} }
/** /**
@@ -823,6 +803,5 @@ class IntExpAssembleStartViewModel : BaseViewModel() {
operator = previousOperator // 恢复组装人 operator = previousOperator // 恢复组装人
} }
isUldNoLocked.value = false isUldNoLocked.value = false
editMode = null
} }
} }

View File

@@ -46,11 +46,13 @@
android:layout_weight="3" android:layout_weight="3"
android:background="@drawable/bg_white_radius_8" android:background="@drawable/bg_white_radius_8"
android:orientation="vertical"> android:orientation="vertical">
<!-- 搜索框 --> <!-- ULD搜索框 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayoutNew <com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayoutNew
hint='@{"请输入ULD编"}' hint='@{"请输入ULD编"}'
icon="@{@drawable/img_search}"
setRefreshCallBack="@{viewModel::onUldSearchInputComplete}"
type="@{SearchLayoutType.INPUT}" type="@{SearchLayoutType.INPUT}"
value="@={viewModel.searchText}" value="@={viewModel.uldSearchText}"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="4dp" /> android:layout_margin="4dp" />