From ca81d8f8bb78b61fba70c2e1e35609cd6b08a297 Mon Sep 17 00:00:00 2001 From: YANGJIANKUAN Date: Tue, 13 Jan 2026 11:16:21 +0800 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20=E5=9B=BD=E9=99=85=E5=87=BA?= =?UTF-8?q?=E6=B8=AF-=E5=87=BA=E6=B8=AF=E4=BB=93=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aerologic/ui/fragment/HomeFragment.kt | 2 +- .../lukouguoji/module_base/bean/GjcMaWb.kt | 31 +++++++++++ .../viewModel/IntExpStorageUseViewModel.kt | 4 +- .../layout/activity_int_exp_storage_use.xml | 11 ++-- .../res/layout/item_int_exp_storage_use.xml | 54 ++++++------------- 5 files changed, 59 insertions(+), 43 deletions(-) diff --git a/app/src/main/java/com/lukouguoji/aerologic/ui/fragment/HomeFragment.kt b/app/src/main/java/com/lukouguoji/aerologic/ui/fragment/HomeFragment.kt index 90ca0fb..7cf65b9 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/ui/fragment/HomeFragment.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/ui/fragment/HomeFragment.kt @@ -753,7 +753,7 @@ class HomeFragment : Fragment() { RightMenu( Constant.AuthName.GjcIntExpStorageUse, R.mipmap.gjc_cang_ku_icon, - "仓库" + "出港仓库" ) ) diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt index a9d05e1..0598e48 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt @@ -1,7 +1,9 @@ package com.lukouguoji.module_base.bean import androidx.databinding.ObservableBoolean +import java.text.SimpleDateFormat import java.util.Date +import java.util.Locale /** * 国际出港主单数据模型 @@ -78,6 +80,7 @@ data class GjcMaWb( var declareStatus: String? = null, // 申报状态 var reviewStatus: String? = null, // 审核状态(0:未审核;1:通过;2:退回) var tranFlag: String? = null, // 转运标志 + var clearNormal: String? = null, // 清仓正常(0:否,1:是) // ==================== 操作信息 ==================== var opDate: String? = null, // 操作时间(入库时间) @@ -145,6 +148,34 @@ data class GjcMaWb( "1" -> "提前运抵" else -> arriveFlag ?: "" } + + /** + * 航班信息(格式化后) + * 格式: yyyyMMdd/航班号 + * 示例: 20260108/MU2025 + */ + val flightInfo: String + get() { + val dateFormat = SimpleDateFormat("yyyyMMdd", Locale.getDefault()) + val formattedDate = fdate?.let { dateFormat.format(it) } ?: "" + val flightNo = fno ?: "" + return if (formattedDate.isNotEmpty() && flightNo.isNotEmpty()) { + "$formattedDate/$flightNo" + } else { + flight ?: "" // 如果无法格式化,回退到原始flight字段 + } + } + + /** + * 清仓正常状态中文 + * 0-否,1-是 + */ + val clearNormalText: String + get() = when (clearNormal) { + "0" -> "否" + "1" -> "是" + else -> clearNormal ?: "" + } } /** diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt index f1d77fb..37efd48 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt @@ -18,6 +18,8 @@ import com.lukouguoji.module_base.ktx.toRequestBody import com.lukouguoji.module_base.model.ScanModel import dev.utils.app.info.KeyValue import kotlinx.coroutines.launch +import java.util.Date +import com.lukouguoji.module_base.ktx.formatDate /** * 国际出港-仓库 ViewModel @@ -25,7 +27,7 @@ import kotlinx.coroutines.launch class IntExpStorageUseViewModel : BasePageViewModel() { // ========== 筛选条件 ========== - val flightDate = MutableLiveData("") // 航班日期 + val flightDate = MutableLiveData(Date().formatDate()) // 航班日期,默认今天 val flightNo = MutableLiveData("") // 航班号 val clearResult = MutableLiveData("") // 清仓综合结果 val clearResultList = MutableLiveData>() // 清仓综合结果列表 diff --git a/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml b/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml index b17b796..fa4ff2b 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml @@ -51,7 +51,7 @@ @@ -199,21 +205,18 @@ diff --git a/module_gjc/src/main/res/layout/item_int_exp_storage_use.xml b/module_gjc/src/main/res/layout/item_int_exp_storage_use.xml index 5df4666..df61f56 100644 --- a/module_gjc/src/main/res/layout/item_int_exp_storage_use.xml +++ b/module_gjc/src/main/res/layout/item_int_exp_storage_use.xml @@ -65,7 +65,7 @@ + android:textSize="16sp" /> @@ -90,7 +88,7 @@ @@ -120,16 +116,14 @@ @@ -138,7 +132,7 @@ @@ -164,22 +156,20 @@ @@ -197,7 +187,7 @@ @@ -221,7 +209,7 @@ @@ -251,16 +237,14 @@ @@ -269,7 +253,7 @@ @@ -293,22 +275,20 @@ From ab4b1618c8ca2352c492fc9c57a2e2250927bc59 Mon Sep 17 00:00:00 2001 From: YANGJIANKUAN Date: Tue, 13 Jan 2026 11:33:23 +0800 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20=E5=9B=BD=E9=99=85=E5=87=BA?= =?UTF-8?q?=E6=B8=AF=20=E5=87=BA=E6=B8=AF=E4=BB=93=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lukouguoji/module_base/bean/GjcMaWb.kt | 5 ++- .../viewModel/IntExpStorageUseViewModel.kt | 32 +++++++++++++++++++ .../layout/activity_int_exp_storage_use.xml | 15 ++++++++- .../res/layout/item_int_exp_storage_use.xml | 4 +-- .../layout/item_int_exp_storage_use_sub.xml | 4 +-- 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt index 0598e48..3169f21 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt @@ -109,7 +109,6 @@ data class GjcMaWb( // ==================== 关联列表(非数据库字段,用于展示) ==================== var haWbList: List? = null, // 分单列表 - @Transient var storageUseList: List? = null, // 库位使用列表 @Transient var attachList: List? = null // 附件列表 @@ -277,10 +276,10 @@ data class GjcStorageUse( var location: String? = null, // 库位号 var storageCode: String? = null, // 库位号(兼容字段) var uld: String? = null, // 板箱号 - var inDate: Date? = null, // 入库时间 + var inDate: String? = null, // 入库时间 var inOpId: String? = null, // 入库人 var inId: String? = null, // 入库人(兼容字段) - var outDate: Date? = null, // 出库时间 + var outDate: String? = null, // 出库时间 var outOpId: String? = null, // 出库人 var outId: String? = null // 出库人(兼容字段) ) { diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt index 37efd48..207ec75 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt @@ -42,6 +42,14 @@ class IntExpStorageUseViewModel : BasePageViewModel() { // ========== 全选状态 ========== val isAllChecked = MutableLiveData(false) + // ========== 全局展开状态 ========== + /** + * 全局展开状态 + * - true: 全部展开 + * - false: 全部收起 + */ + val isAllExpanded = MutableLiveData(false) + init { // 初始化清仓综合结果列表(根据实际需求配置) clearResultList.value = listOf( @@ -82,6 +90,28 @@ class IntExpStorageUseViewModel : BasePageViewModel() { pageModel.rv?.commonAdapter()?.notifyDataSetChanged() } + /** + * 切换全局展开/收起状态 + */ + fun toggleAllExpand() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + + // 切换全局状态 + val shouldExpand = !isAllExpanded.value!! + isAllExpanded.value = shouldExpand + + // 更新所有列表项的 showMore 状态 + list.forEach { bean -> + // 只有当有子列表时才设置展开状态 + if (!bean.storageUseList.isNullOrEmpty()) { + bean.showMore.set(shouldExpand) + } + } + + // 刷新列表UI + pageModel.rv?.commonAdapter()?.notifyDataSetChanged() + } + /** * 扫码运单号 */ @@ -180,6 +210,8 @@ class IntExpStorageUseViewModel : BasePageViewModel() { // 手动处理 PageInfo 数据 pageModel.handleDataList(result.list) pageModel.haveMore.postValue((result.pages) > pageModel.page) + // 数据加载完成后,重置全局展开状态为收起 + isAllExpanded.value = false } } diff --git a/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml b/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml index fa4ff2b..7c0acf8 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml @@ -7,6 +7,8 @@ + + @@ -87,7 +89,7 @@ + + + diff --git a/module_gjc/src/main/res/layout/item_int_exp_storage_use.xml b/module_gjc/src/main/res/layout/item_int_exp_storage_use.xml index df61f56..3a221c7 100644 --- a/module_gjc/src/main/res/layout/item_int_exp_storage_use.xml +++ b/module_gjc/src/main/res/layout/item_int_exp_storage_use.xml @@ -156,7 +156,7 @@ @@ -81,7 +81,7 @@ android:layout_gravity="center_vertical" android:layout_weight="1.5" android:gravity="center" - android:text="@{bean.outDate != null ? bean.outDate.toString() : ``}" + android:text="@{bean.outDate ?? ``}" android:textColor="@color/text_normal" android:textSize="14sp" /> From 4e34a8f406fe07a205d0d81c6005a550fbc84722 Mon Sep 17 00:00:00 2001 From: YANGJIANKUAN Date: Tue, 13 Jan 2026 11:49:38 +0800 Subject: [PATCH 3/9] =?UTF-8?q?feat:=20=E5=9B=BD=E9=99=85=E5=87=BA?= =?UTF-8?q?=E6=B8=AF=20=E5=87=BA=E6=B8=AF=E7=A7=BB=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gjc/viewModel/IntExpMoveViewModel.kt | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveViewModel.kt index ccdf2bf..441616e 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveViewModel.kt @@ -31,18 +31,17 @@ class IntExpMoveViewModel : BasePageViewModel(), IOnItemClickListener { // ========== 运单类型下拉数据 ========== val awbTypeList = MutableLiveData>().apply { value = listOf( - KeyValue("", "全部"), - KeyValue("IOCO", "国际出港(经国内航班出境)"), - KeyValue("IOSO", "国际出港(国际航班出境)") + KeyValue("全部", ""), + KeyValue("转国内出港", "IOCO") ) } // ========== 移库状态下拉数据 ========== val moveStateList = MutableLiveData>().apply { value = listOf( - KeyValue("", "全部"), - KeyValue("0", "未移交"), - KeyValue("1", "已移交") + KeyValue("全部", ""), + KeyValue("未移库", "0"), + KeyValue("已移库", "1") ) } @@ -146,14 +145,14 @@ class IntExpMoveViewModel : BasePageViewModel(), IOnItemClickListener { * 获取列表数据 */ override fun getData() { - // 构建筛选参数 - val filterParams = mapOf( - "awbType" to awbType.value.noNull(), - "by1" to by1.value.noNull(), - "dest1" to dest1.value.noNull(), - "moveState" to moveState.value.noNull(), - "wbNo" to waybillNo.value.noNull() - ) + // 构建筛选参数(只传递非空值) + val filterParams = mutableMapOf() + + awbType.value?.takeIf { it.isNotEmpty() }?.let { filterParams["awbType"] = it } + by1.value?.takeIf { it.isNotEmpty() }?.let { filterParams["by1"] = it } + dest1.value?.takeIf { it.isNotEmpty() }?.let { filterParams["dest1"] = it } + moveState.value?.takeIf { it.isNotEmpty() }?.let { filterParams["moveState"] = it } + waybillNo.value?.takeIf { it.isNotEmpty() }?.let { filterParams["wbNo"] = it } // 列表参数(含分页) val listParams = (filterParams + mapOf( From 49151d00663b3f930438f96e21b0dce8450353fa Mon Sep 17 00:00:00 2001 From: YANGJIANKUAN Date: Tue, 13 Jan 2026 11:54:26 +0800 Subject: [PATCH 4/9] =?UTF-8?q?feat:=20=E5=9B=BD=E9=99=85=E5=87=BA?= =?UTF-8?q?=E6=B8=AF=20=E5=87=BA=E6=B8=AF=E4=BB=93=E5=BA=93=20opt=20filter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../viewModel/IntExpStorageUseViewModel.kt | 13 +++++------ .../layout/activity_int_exp_storage_use.xml | 22 +++++++++---------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt index 207ec75..4247b30 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt @@ -1,25 +1,21 @@ package com.lukouguoji.gjc.viewModel import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.viewModelScope import com.lukouguoji.gjc.R import com.lukouguoji.gjc.holder.IntExpStorageUseViewHolder import com.lukouguoji.module_base.base.BasePageViewModel import com.lukouguoji.module_base.bean.GjcMaWb import com.lukouguoji.module_base.common.Constant -import com.lukouguoji.module_base.common.ConstantEvent import com.lukouguoji.module_base.http.net.NetApply -import com.lukouguoji.module_base.impl.FlowBus import com.lukouguoji.module_base.ktx.commonAdapter +import com.lukouguoji.module_base.ktx.formatDate import com.lukouguoji.module_base.ktx.launchCollect import com.lukouguoji.module_base.ktx.launchLoadingCollect import com.lukouguoji.module_base.ktx.showToast import com.lukouguoji.module_base.ktx.toRequestBody import com.lukouguoji.module_base.model.ScanModel import dev.utils.app.info.KeyValue -import kotlinx.coroutines.launch import java.util.Date -import com.lukouguoji.module_base.ktx.formatDate /** * 国际出港-仓库 ViewModel @@ -32,7 +28,7 @@ class IntExpStorageUseViewModel : BasePageViewModel() { val clearResult = MutableLiveData("") // 清仓综合结果 val clearResultList = MutableLiveData>() // 清仓综合结果列表 val wbNo = MutableLiveData("") // 运单号 - val storageCode = MutableLiveData("") // 库位号 + val location = MutableLiveData("") // 库位号 // ========== 统计信息 ========== val totalWbNumber = MutableLiveData("0") // 总票数 @@ -60,7 +56,8 @@ class IntExpStorageUseViewModel : BasePageViewModel() { // 监听全选状态,自动更新所有列表项 isAllChecked.observeForever { checked -> - val list = pageModel.rv?.commonAdapter()?.items as? List ?: return@observeForever + val list = + pageModel.rv?.commonAdapter()?.items as? List ?: return@observeForever list.forEach { it.checked.set(checked) } pageModel.rv?.commonAdapter()?.notifyDataSetChanged() } @@ -192,7 +189,7 @@ class IntExpStorageUseViewModel : BasePageViewModel() { "fdate" to flightDate.value?.ifEmpty { null }, "fno" to flightNo.value?.ifEmpty { null }, "wbNo" to wbNo.value?.ifEmpty { null }, - "storageCode" to storageCode.value?.ifEmpty { null } + "location" to location.value?.ifEmpty { null } ) // 列表参数 (含分页) diff --git a/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml b/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml index 7c0acf8..4f267cf 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml @@ -44,9 +44,9 @@ @@ -63,17 +63,17 @@ @@ -82,7 +82,7 @@ @@ -104,14 +104,14 @@ + android:scaleType="fitCenter" /> From 557874ab88e3db9ba4591998a8b8b36a9fd39703 Mon Sep 17 00:00:00 2001 From: YANGJIANKUAN Date: Wed, 14 Jan 2026 17:21:01 +0800 Subject: [PATCH 5/9] =?UTF-8?q?feat:=20=E5=9B=BD=E9=99=85=E5=87=BA?= =?UTF-8?q?=E6=B8=AF=20=E5=87=BA=E6=B8=AF=E4=BB=93=E5=BA=93=20=E6=B8=85?= =?UTF-8?q?=E4=BB=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lukouguoji/module_base/http/net/Api.kt | 7 ++ .../gjc/activity/IntExpStorageUseActivity.kt | 25 ++++++ .../gjc/dialog/IntExpMoveClearDialogModel.kt | 47 ++++++++++ .../gjc/page/move/IntExpMoveActivity.kt | 25 ++++++ .../viewModel/IntExpStorageUseViewModel.kt | 37 +++++++- .../main/res/layout/activity_int_exp_move.xml | 7 ++ .../layout/activity_int_exp_storage_use.xml | 6 +- .../res/layout/dialog_int_exp_move_clear.xml | 86 +++++++++++++++++++ 8 files changed, 235 insertions(+), 5 deletions(-) create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpMoveClearDialogModel.kt create mode 100644 module_gjc/src/main/res/layout/dialog_int_exp_move_clear.xml diff --git a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt index 27bbef5..bad9704 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt @@ -811,6 +811,13 @@ interface Api { @POST("IntExpMove/move") suspend fun submitIntExpMove(@Body data: RequestBody): BaseResultBean + /** + * 国际出港库位操作-清仓 + * 接口路径: /IntExpStorageUse/updateClear + */ + @POST("IntExpStorageUse/updateClear") + suspend fun clearIntExpStorage(@Body data: RequestBody): BaseResultBean + /** * 国际出港仓库-分页查询 * 接口路径: /IntExpStorageUse/pageQuery diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt index f876f58..6854b63 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt @@ -6,12 +6,15 @@ import android.os.Bundle import com.alibaba.android.arouter.facade.annotation.Route import com.lukouguoji.gjc.R import com.lukouguoji.gjc.databinding.ActivityIntExpStorageUseBinding +import com.lukouguoji.gjc.dialog.IntExpMoveClearDialogModel import com.lukouguoji.gjc.viewModel.IntExpStorageUseViewModel import com.lukouguoji.module_base.base.BaseBindingActivity import com.lukouguoji.module_base.common.Constant 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.ktx.commonAdapter +import com.lukouguoji.module_base.ktx.showToast import com.lukouguoji.module_base.router.ARouterConstants /** @@ -27,6 +30,7 @@ class IntExpStorageUseActivity : override fun initOnCreate(savedInstanceState: Bundle?) { setBackArrow("国际出港仓库") binding.viewModel = viewModel + binding.activity = this // 观察全选状态,更新图标透明度 viewModel.isAllChecked.observe(this) { isAllChecked -> @@ -45,6 +49,27 @@ class IntExpStorageUseActivity : viewModel.refresh() } + /** + * 显示清仓操作对话框 + */ + fun showClearDialog() { + val list = viewModel.pageModel.rv?.commonAdapter()?.items as? List<*> ?: return + val selectedItems = list.filterIsInstance() + .filter { it.isSelected } + + if (selectedItems.isEmpty()) { + showToast("请至少选择一条运单") + return + } + + // 显示清仓对话框 + IntExpMoveClearDialogModel { dialog -> + // 用户点击保存后,执行清仓操作 + val clearNormal = dialog.clearNormal.value ?: "" + viewModel.performClear(clearNormal) + }.show(this) + } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == Constant.RequestCode.WAYBILL && resultCode == Activity.RESULT_OK) { diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpMoveClearDialogModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpMoveClearDialogModel.kt new file mode 100644 index 0000000..8af9afa --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpMoveClearDialogModel.kt @@ -0,0 +1,47 @@ +package com.lukouguoji.gjc.dialog + +import android.content.Context +import androidx.lifecycle.MutableLiveData +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.DialogIntExpMoveClearBinding +import com.lukouguoji.module_base.base.BaseDialogModel +import com.lukouguoji.module_base.ktx.verifyNullOrEmpty +import dev.utils.app.info.KeyValue + +/** + * 国际出港移库 - 清仓操作对话框 + */ +class IntExpMoveClearDialogModel( + private val callback: (IntExpMoveClearDialogModel) -> Unit +) : BaseDialogModel(DIALOG_TYPE_CENTER) { + + // 清仓正常(存储的是 code:"0" 或 "1") + val clearNormal = MutableLiveData("") + + // 清仓正常选项列表 + val clearNormalList = MutableLiveData>().apply { + value = listOf( + KeyValue("是", "1"), + KeyValue("否", "0") + ) + } + + override fun layoutId(): Int { + return R.layout.dialog_int_exp_move_clear + } + + override fun onDialogCreated(context: Context) { + binding.model = this + } + + /** + * 保存按钮点击 + */ + fun onSaveClick() { + if (clearNormal.value.verifyNullOrEmpty("请选择清仓正常")) { + return + } + dismiss() + callback(this) + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt index 1a918b3..7c00fa3 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt @@ -8,6 +8,7 @@ import androidx.appcompat.app.AlertDialog import com.alibaba.android.arouter.facade.annotation.Route import com.lukouguoji.gjc.R import com.lukouguoji.gjc.databinding.ActivityIntExpMoveBinding +import com.lukouguoji.gjc.dialog.IntExpMoveClearDialogModel import com.lukouguoji.gjc.viewModel.IntExpMoveViewModel import com.lukouguoji.module_base.base.BaseBindingActivity import com.lukouguoji.module_base.common.Constant @@ -55,6 +56,11 @@ class IntExpMoveActivity : BaseBindingActivity + // 用户点击保存后,执行清仓操作 + val clearNormal = dialog.clearNormal.value ?: "" + viewModel.performClear(clearNormal) + }.show(this) + } + /** * 扫码回调 */ diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt index 4247b30..a73eeee 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt @@ -1,20 +1,25 @@ package com.lukouguoji.gjc.viewModel import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope import com.lukouguoji.gjc.R import com.lukouguoji.gjc.holder.IntExpStorageUseViewHolder import com.lukouguoji.module_base.base.BasePageViewModel import com.lukouguoji.module_base.bean.GjcMaWb import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.common.ConstantEvent import com.lukouguoji.module_base.http.net.NetApply +import com.lukouguoji.module_base.impl.FlowBus import com.lukouguoji.module_base.ktx.commonAdapter import com.lukouguoji.module_base.ktx.formatDate import com.lukouguoji.module_base.ktx.launchCollect import com.lukouguoji.module_base.ktx.launchLoadingCollect +import com.lukouguoji.module_base.ktx.noNull import com.lukouguoji.module_base.ktx.showToast import com.lukouguoji.module_base.ktx.toRequestBody import com.lukouguoji.module_base.model.ScanModel import dev.utils.app.info.KeyValue +import kotlinx.coroutines.launch import java.util.Date /** @@ -117,19 +122,43 @@ class IntExpStorageUseViewModel : BasePageViewModel() { } /** - * 清仓操作 + * 清仓操作(在Activity中调用,会显示对话框) */ fun clearStorage() { + // 由Activity显示对话框 + } + + /** + * 执行清仓操作 + * @param clearNormal 清仓正常("0"或"1") + */ + fun performClear(clearNormal: String) { val list = pageModel.rv?.commonAdapter()?.items as? List ?: return val selectedItems = list.filter { it.isSelected } if (selectedItems.isEmpty()) { - showToast("请选择要清仓的运单") + showToast("请至少选择一条运单") return } - // TODO: 实现清仓接口调用 - showToast("清仓功能待实现") + // 构建请求参数 + val params = mapOf( + "clearNormal" to clearNormal, + "maWbList" to selectedItems + ).toRequestBody() + + launchLoadingCollect({ NetApply.api.clearIntExpStorage(params) }) { + onSuccess = { + showToast("清仓成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + refresh() // 刷新列表 + } + onFailed = { _, msg -> + showToast(msg.noNull("清仓失败")) + } + } } /** diff --git a/module_gjc/src/main/res/layout/activity_int_exp_move.xml b/module_gjc/src/main/res/layout/activity_int_exp_move.xml index 95b066c..1f1b440 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_move.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_move.xml @@ -194,6 +194,13 @@ android:textStyle="bold" /> + + + + + diff --git a/module_gjc/src/main/res/layout/dialog_int_exp_move_clear.xml b/module_gjc/src/main/res/layout/dialog_int_exp_move_clear.xml new file mode 100644 index 0000000..213c10a --- /dev/null +++ b/module_gjc/src/main/res/layout/dialog_int_exp_move_clear.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 76183823b056b0c9484899c2fe625d52f1f6d512 Mon Sep 17 00:00:00 2001 From: YANGJIANKUAN Date: Wed, 14 Jan 2026 17:24:50 +0800 Subject: [PATCH 6/9] =?UTF-8?q?feat:=20=E5=9B=BD=E9=99=85=E5=87=BA?= =?UTF-8?q?=E6=B8=AF=20=E5=87=BA=E6=B8=AF=E4=BB=93=E5=BA=93=20=E6=B8=85?= =?UTF-8?q?=E4=BB=93=20v2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gjc/page/move/IntExpMoveActivity.kt | 25 ------------------- .../main/res/layout/activity_int_exp_move.xml | 7 ------ 2 files changed, 32 deletions(-) diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt index 7c00fa3..1a918b3 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt @@ -8,7 +8,6 @@ import androidx.appcompat.app.AlertDialog import com.alibaba.android.arouter.facade.annotation.Route import com.lukouguoji.gjc.R import com.lukouguoji.gjc.databinding.ActivityIntExpMoveBinding -import com.lukouguoji.gjc.dialog.IntExpMoveClearDialogModel import com.lukouguoji.gjc.viewModel.IntExpMoveViewModel import com.lukouguoji.module_base.base.BaseBindingActivity import com.lukouguoji.module_base.common.Constant @@ -56,11 +55,6 @@ class IntExpMoveActivity : BaseBindingActivity - // 用户点击保存后,执行清仓操作 - val clearNormal = dialog.clearNormal.value ?: "" - viewModel.performClear(clearNormal) - }.show(this) - } - /** * 扫码回调 */ diff --git a/module_gjc/src/main/res/layout/activity_int_exp_move.xml b/module_gjc/src/main/res/layout/activity_int_exp_move.xml index 1f1b440..95b066c 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_move.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_move.xml @@ -194,13 +194,6 @@ android:textStyle="bold" /> - - - Date: Wed, 14 Jan 2026 18:39:15 +0800 Subject: [PATCH 7/9] =?UTF-8?q?feat:=20=E5=9B=BD=E9=99=85=E5=87=BA?= =?UTF-8?q?=E6=B8=AF=20=E5=87=BA=E6=B8=AF=E4=BB=93=E5=BA=93=20=E4=BB=93?= =?UTF-8?q?=E4=BD=8D=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lukouguoji/module_base/bean/GjcMaWb.kt | 4 +- .../lukouguoji/module_base/http/net/Api.kt | 7 ++ .../gjc/activity/IntExpStorageUseActivity.kt | 60 +++++++++++-- .../dialog/IntExpModifyStorageDialogModel.kt | 38 ++++++++ .../holder/IntExpStorageUseSubViewHolder.kt | 29 ++++++- .../gjc/holder/IntExpStorageUseViewHolder.kt | 21 ++++- .../viewModel/IntExpStorageUseViewModel.kt | 83 +++++++++++++----- .../layout/activity_int_exp_storage_use.xml | 2 +- .../layout/dialog_int_exp_modify_storage.xml | 86 +++++++++++++++++++ 9 files changed, 295 insertions(+), 35 deletions(-) create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpModifyStorageDialogModel.kt create mode 100644 module_gjc/src/main/res/layout/dialog_int_exp_modify_storage.xml diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt index 3169f21..a5b605d 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt @@ -274,6 +274,7 @@ data class GjcStorageUse( var prefix: String? = null, // 运单前缀 var no: String? = null, // 运单号 var location: String? = null, // 库位号 + var locationId: Long? = null, // 库位id var storageCode: String? = null, // 库位号(兼容字段) var uld: String? = null, // 板箱号 var inDate: String? = null, // 入库时间 @@ -281,7 +282,8 @@ data class GjcStorageUse( var inId: String? = null, // 入库人(兼容字段) var outDate: String? = null, // 出库时间 var outOpId: String? = null, // 出库人 - var outId: String? = null // 出库人(兼容字段) + var outId: String? = null, // 出库人(兼容字段) + var cargoStatus: String? = null // 货物状态 ) { // ==================== UI扩展字段 ==================== @Transient diff --git a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt index bad9704..70237aa 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt @@ -818,6 +818,13 @@ interface Api { @POST("IntExpStorageUse/updateClear") suspend fun clearIntExpStorage(@Body data: RequestBody): BaseResultBean + /** + * 国际出港库位操作-修改库位 + * 接口路径: /IntExpStorageUse/modifyStorage + */ + @POST("IntExpStorageUse/modifyStorage") + suspend fun modifyIntExpStorage(@Body data: RequestBody): BaseResultBean + /** * 国际出港仓库-分页查询 * 接口路径: /IntExpStorageUse/pageQuery diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt index 6854b63..14628f1 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt @@ -7,6 +7,7 @@ import com.alibaba.android.arouter.facade.annotation.Route import com.lukouguoji.gjc.R import com.lukouguoji.gjc.databinding.ActivityIntExpStorageUseBinding import com.lukouguoji.gjc.dialog.IntExpMoveClearDialogModel +import com.lukouguoji.gjc.dialog.IntExpModifyStorageDialogModel import com.lukouguoji.gjc.viewModel.IntExpStorageUseViewModel import com.lukouguoji.module_base.base.BaseBindingActivity import com.lukouguoji.module_base.common.Constant @@ -54,11 +55,25 @@ class IntExpStorageUseActivity : */ fun showClearDialog() { val list = viewModel.pageModel.rv?.commonAdapter()?.items as? List<*> ?: return - val selectedItems = list.filterIsInstance() - .filter { it.isSelected } + val allItems = list.filterIsInstance() - if (selectedItems.isEmpty()) { - showToast("请至少选择一条运单") + // 构建清仓数据:保留主列表结构,但只包含选中的子列表项 + val maWbListForClear = allItems.mapNotNull { maWb -> + // 过滤出选中的子列表项 + val selectedStorageList = maWb.storageUseList?.filter { it.isSelected } ?: emptyList() + + // 只添加有选中子列表项的主列表项 + if (selectedStorageList.isNotEmpty()) { + // 创建主列表项的副本,只包含选中的子列表 + maWb.copy(storageUseList = selectedStorageList) + } else { +// null + maWb + } + } + + if (maWbListForClear.isEmpty()) { + showToast("请至少选择一个库位") return } @@ -66,7 +81,42 @@ class IntExpStorageUseActivity : IntExpMoveClearDialogModel { dialog -> // 用户点击保存后,执行清仓操作 val clearNormal = dialog.clearNormal.value ?: "" - viewModel.performClear(clearNormal) + viewModel.performClear(clearNormal, maWbListForClear) + }.show(this) + } + + /** + * 显示修改库位对话框 + */ + fun showModifyStorageDialog() { + val list = viewModel.pageModel.rv?.commonAdapter()?.items as? List<*> ?: return + val allItems = list.filterIsInstance() + + // 收集所有选中的子列表项(库位) + val selectedStorageUseList = mutableListOf() + allItems.forEach { maWb -> + maWb.storageUseList?.filter { it.isSelected }?.let { selectedStorageUseList.addAll(it) } + } + + // 校验:必须且只能选中一个库位 + when { + selectedStorageUseList.isEmpty() -> { + showToast("请选择要修改的库位") + return + } + selectedStorageUseList.size > 1 -> { + showToast("只能选择一个库位进行修改") + return + } + } + + val selectedStorage = selectedStorageUseList[0] + + // 显示修改库位对话框 + IntExpModifyStorageDialogModel { dialog -> + // 用户点击保存后,执行修改库位操作 + val newLocation = dialog.location.value ?: "" + viewModel.performModifyStorage(newLocation, selectedStorage) }.show(this) } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpModifyStorageDialogModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpModifyStorageDialogModel.kt new file mode 100644 index 0000000..1520172 --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpModifyStorageDialogModel.kt @@ -0,0 +1,38 @@ +package com.lukouguoji.gjc.dialog + +import android.content.Context +import androidx.lifecycle.MutableLiveData +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.DialogIntExpModifyStorageBinding +import com.lukouguoji.module_base.base.BaseDialogModel +import com.lukouguoji.module_base.ktx.verifyNullOrEmpty + +/** + * 国际出港 - 修改库位对话框 + */ +class IntExpModifyStorageDialogModel( + private val callback: (IntExpModifyStorageDialogModel) -> Unit +) : BaseDialogModel(DIALOG_TYPE_CENTER) { + + // 库位号 + val location = MutableLiveData("") + + override fun layoutId(): Int { + return R.layout.dialog_int_exp_modify_storage + } + + override fun onDialogCreated(context: Context) { + binding.model = this + } + + /** + * 保存按钮点击 + */ + fun onSaveClick() { + if (location.value.verifyNullOrEmpty("请输入库位号")) { + return + } + dismiss() + callback(this) + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseSubViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseSubViewHolder.kt index 491e1a0..c735855 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseSubViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseSubViewHolder.kt @@ -1,8 +1,10 @@ package com.lukouguoji.gjc.holder import android.view.View +import androidx.recyclerview.widget.RecyclerView import com.lukouguoji.gjc.databinding.ItemIntExpStorageUseSubBinding import com.lukouguoji.module_base.base.BaseViewHolder +import com.lukouguoji.module_base.bean.GjcMaWb import com.lukouguoji.module_base.bean.GjcStorageUse /** @@ -17,10 +19,33 @@ class IntExpStorageUseSubViewHolder(view: View) : binding.position = position binding.executePendingBindings() - // 单选框点击切换选择状态 + // 单选框点击切换选择状态(反向联动主列表) binding.ivCheckbox.setOnClickListener { - bean.checked.set(!bean.checked.get()) + // 切换子列表项的选择状态 + val newCheckedState = !bean.checked.get() + bean.checked.set(newCheckedState) binding.executePendingBindings() + + // 反向联动主列表项 + updateParentCheckState() } } + + /** + * 更新父列表项的选择状态 + * 规则: + * - 如果有任何一个子列表项被勾选,则主列表项也应该被勾选 + * - 如果所有子列表项都未勾选,则主列表项也应该取消勾选 + */ + private fun updateParentCheckState() { + // 从RecyclerView的tag获取父Bean引用 + val recyclerView = itemView.parent as? RecyclerView ?: return + val parentBean = recyclerView.tag as? GjcMaWb ?: return + + // 检查是否有任何一个子列表项被勾选 + val hasAnyChecked = parentBean.storageUseList?.any { it.checked.get() } ?: false + + // 更新父列表项的选择状态 + parentBean.checked.set(hasAnyChecked) + } } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseViewHolder.kt index df097a0..afa0696 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseViewHolder.kt @@ -20,10 +20,20 @@ class IntExpStorageUseViewHolder(view: View) : binding.position = position binding.executePendingBindings() - // 图标点击切换选择状态 + // 图标点击切换选择状态(联动子列表) binding.ivIcon.setOnClickListener { - bean.checked.set(!bean.checked.get()) + // 切换主列表项的选择状态 + val newCheckedState = !bean.checked.get() + bean.checked.set(newCheckedState) + + // 联动勾选/取消所有子列表项 + bean.storageUseList?.forEach { storageUse -> + storageUse.checked.set(newCheckedState) + } + + // 刷新UI binding.executePendingBindings() + binding.rvSub.adapter?.notifyDataSetChanged() } // 展开按钮点击事件 @@ -38,7 +48,10 @@ class IntExpStorageUseViewHolder(view: View) : R.layout.item_int_exp_storage_use_sub ) - // 刷新库位明细数据 - binding.rvSub.refresh(bean.storageUseList ?: emptyList()) + // 刷新库位明细数据(传递父Bean引用) + val storageUseList = bean.storageUseList ?: emptyList() + // 为每个子列表项设置父Bean引用(通过tag传递) + binding.rvSub.tag = bean + binding.rvSub.refresh(storageUseList) } } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt index a73eeee..cfa3201 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt @@ -80,13 +80,22 @@ class IntExpStorageUseViewModel : BasePageViewModel() { } /** - * 全选按钮点击 + * 全选按钮点击(联动勾选所有子列表项) */ fun checkAllClick() { val list = pageModel.rv?.commonAdapter()?.items as? List ?: return val shouldCheckAll = !isAllChecked.value!! - list.forEach { it.checked.set(shouldCheckAll) } + + // 联动勾选/取消主列表和子列表 + list.forEach { maWb -> + maWb.checked.set(shouldCheckAll) + // 同时联动勾选/取消所有子列表项 + maWb.storageUseList?.forEach { storageUse -> + storageUse.checked.set(shouldCheckAll) + } + } + isAllChecked.value = shouldCheckAll pageModel.rv?.commonAdapter()?.notifyDataSetChanged() @@ -131,20 +140,18 @@ class IntExpStorageUseViewModel : BasePageViewModel() { /** * 执行清仓操作 * @param clearNormal 清仓正常("0"或"1") + * @param maWbListForClear 包含选中子列表项的主列表数据 */ - fun performClear(clearNormal: String) { - val list = pageModel.rv?.commonAdapter()?.items as? List ?: return - val selectedItems = list.filter { it.isSelected } - - if (selectedItems.isEmpty()) { - showToast("请至少选择一条运单") + fun performClear(clearNormal: String, maWbListForClear: List) { + if (maWbListForClear.isEmpty()) { + showToast("请至少选择一个库位") return } - // 构建请求参数 + // 构建请求参数:完整的主子列表结构 val params = mapOf( "clearNormal" to clearNormal, - "maWbList" to selectedItems + "maWbList" to maWbListForClear ).toRequestBody() launchLoadingCollect({ NetApply.api.clearIntExpStorage(params) }) { @@ -165,16 +172,38 @@ class IntExpStorageUseViewModel : BasePageViewModel() { * 修改库位 */ fun modifyStorage() { - val list = pageModel.rv?.commonAdapter()?.items as? List ?: return - val selectedItems = list.filter { it.isSelected } + // 由Activity显示对话框 + } - if (selectedItems.isEmpty()) { - showToast("请选择要修改库位的运单") + /** + * 执行修改库位操作 + * @param newLocation 新的库位号 + * @param storageUse 选中的单个库位使用对象 + */ + fun performModifyStorage(newLocation: String, storageUse: com.lukouguoji.module_base.bean.GjcStorageUse) { + if (newLocation.isEmpty()) { + showToast("请输入新的库位号") return } - // TODO: 实现修改库位接口调用或弹出对话框 - showToast("修改库位功能待实现") + // 创建更新后的库位对象(覆盖 location 字段) + val updatedStorage = storageUse.copy(location = newLocation) + + // 直接使用更新后的对象构建请求参数 + val params = updatedStorage.toRequestBody() + + launchLoadingCollect({ NetApply.api.modifyIntExpStorage(params) }) { + onSuccess = { + showToast("修改库位成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + refresh() // 刷新列表 + } + onFailed = { _, msg -> + showToast(msg.noNull("修改库位失败")) + } + } } /** @@ -182,10 +211,15 @@ class IntExpStorageUseViewModel : BasePageViewModel() { */ fun outStorage() { val list = pageModel.rv?.commonAdapter()?.items as? List ?: return - val selectedItems = list.filter { it.isSelected } - if (selectedItems.isEmpty()) { - showToast("请选择要出库的运单") + // 收集所有选中的子列表项(库位) + val selectedStorageUseList = mutableListOf() + list.forEach { maWb -> + maWb.storageUseList?.filter { it.isSelected }?.let { selectedStorageUseList.addAll(it) } + } + + if (selectedStorageUseList.isEmpty()) { + showToast("请选择要出库的库位") return } @@ -198,10 +232,15 @@ class IntExpStorageUseViewModel : BasePageViewModel() { */ fun inStorage() { val list = pageModel.rv?.commonAdapter()?.items as? List ?: return - val selectedItems = list.filter { it.isSelected } - if (selectedItems.isEmpty()) { - showToast("请选择要入库的运单") + // 收集所有选中的子列表项(库位) + val selectedStorageUseList = mutableListOf() + list.forEach { maWb -> + maWb.storageUseList?.filter { it.isSelected }?.let { selectedStorageUseList.addAll(it) } + } + + if (selectedStorageUseList.isEmpty()) { + showToast("请选择要入库的库位") return } diff --git a/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml b/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml index 8aefcc9..845de19 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml @@ -228,7 +228,7 @@ diff --git a/module_gjc/src/main/res/layout/dialog_int_exp_modify_storage.xml b/module_gjc/src/main/res/layout/dialog_int_exp_modify_storage.xml new file mode 100644 index 0000000..51537c3 --- /dev/null +++ b/module_gjc/src/main/res/layout/dialog_int_exp_modify_storage.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From a8d125ef9d29adfe5ae7e2b235ed4431568b9d76 Mon Sep 17 00:00:00 2001 From: YANGJIANKUAN Date: Thu, 15 Jan 2026 17:23:48 +0800 Subject: [PATCH 8/9] =?UTF-8?q?feat:=20=E5=9B=BD=E9=99=85=E5=87=BA?= =?UTF-8?q?=E6=B8=AF=20=E5=87=BA=E6=B8=AF=E4=BB=93=E5=BA=93=20=E6=B8=85?= =?UTF-8?q?=E4=BB=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vfox.toml | 2 ++ .vfox/sdks/java | 1 + .../gjc/activity/IntExpStorageUseActivity.kt | 5 ++--- .../holder/IntExpStorageUseSubViewHolder.kt | 20 +++++++++---------- .../gjc/holder/IntExpTallyViewHolder.kt | 14 +++++++++++-- .../gjc/viewModel/IntExpTallyViewModel.kt | 13 ++++++++++-- 6 files changed, 38 insertions(+), 17 deletions(-) create mode 100644 .vfox.toml create mode 120000 .vfox/sdks/java diff --git a/.vfox.toml b/.vfox.toml new file mode 100644 index 0000000..9dbc9e4 --- /dev/null +++ b/.vfox.toml @@ -0,0 +1,2 @@ +[tools] +java = "17.0.16+8-amzn" diff --git a/.vfox/sdks/java b/.vfox/sdks/java new file mode 120000 index 0000000..d309154 --- /dev/null +++ b/.vfox/sdks/java @@ -0,0 +1 @@ +/Users/kid/.version-fox/cache/java/v-17.0.16+8-amzn/java-17.0.16+8-amzn \ No newline at end of file diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt index 14628f1..15d2c56 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt @@ -63,12 +63,11 @@ class IntExpStorageUseActivity : val selectedStorageList = maWb.storageUseList?.filter { it.isSelected } ?: emptyList() // 只添加有选中子列表项的主列表项 - if (selectedStorageList.isNotEmpty()) { + if (selectedStorageList.isNotEmpty() || maWb.isSelected) { // 创建主列表项的副本,只包含选中的子列表 maWb.copy(storageUseList = selectedStorageList) } else { -// null - maWb + null } } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseSubViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseSubViewHolder.kt index c735855..97ceef6 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseSubViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseSubViewHolder.kt @@ -26,26 +26,26 @@ class IntExpStorageUseSubViewHolder(view: View) : bean.checked.set(newCheckedState) binding.executePendingBindings() - // 反向联动主列表项 - updateParentCheckState() + // 反向联动主列表项(仅在勾选时联动) + updateParentCheckState(newCheckedState) } } /** * 更新父列表项的选择状态 * 规则: - * - 如果有任何一个子列表项被勾选,则主列表项也应该被勾选 - * - 如果所有子列表项都未勾选,则主列表项也应该取消勾选 + * - 如果子项被勾选(newCheckedState = true),则自动勾选父项 + * - 如果子项被取消勾选(newCheckedState = false),则不改变父项状态 */ - private fun updateParentCheckState() { + private fun updateParentCheckState(newCheckedState: Boolean) { // 从RecyclerView的tag获取父Bean引用 val recyclerView = itemView.parent as? RecyclerView ?: return val parentBean = recyclerView.tag as? GjcMaWb ?: return - // 检查是否有任何一个子列表项被勾选 - val hasAnyChecked = parentBean.storageUseList?.any { it.checked.get() } ?: false - - // 更新父列表项的选择状态 - parentBean.checked.set(hasAnyChecked) + // 只有当子项被勾选时,才联动勾选父项 + if (newCheckedState) { + parentBean.checked.set(true) + } + // 当子项被取消勾选时,不影响父项状态 } } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpTallyViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpTallyViewHolder.kt index 60f7324..661c87f 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpTallyViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpTallyViewHolder.kt @@ -20,10 +20,20 @@ class IntExpTallyViewHolder(view: View) : binding.position = position binding.executePendingBindings() - // 图标点击切换选择状态(保留原有) + // 图标点击切换选择状态(单向同步到子列表) binding.ivIcon.setOnClickListener { - bean.checked.set(!bean.checked.get()) + // 切换主列表项的选择状态 + val newCheckedState = !bean.checked.get() + bean.checked.set(newCheckedState) + + // 单向同步:主列表选择状态同步到所有子列表项 + bean.haWbList?.forEach { haWb -> + haWb.checked.set(newCheckedState) + } + + // 刷新UI binding.executePendingBindings() + binding.rvSub.adapter?.notifyDataSetChanged() } // ========== 新增:展开按钮点击事件 ========== diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpTallyViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpTallyViewModel.kt index 1d4af55..278852b 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpTallyViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpTallyViewModel.kt @@ -71,14 +71,23 @@ class IntExpTallyViewModel : BasePageViewModel() { } /** - * 全选按钮点击 (切换全选状态) + * 全选按钮点击 (切换全选状态,单向同步到子列表) */ fun checkAllClick() { val list = pageModel.rv?.commonAdapter()?.items as? List ?: return // 切换全选状态 val shouldCheckAll = !isAllChecked.value!! - list.forEach { it.checked.set(shouldCheckAll) } + + // 单向同步:主列表和子列表都设置为相同的选择状态 + list.forEach { maWb -> + maWb.checked.set(shouldCheckAll) + // 同步到所有子列表项 + maWb.haWbList?.forEach { haWb -> + haWb.checked.set(shouldCheckAll) + } + } + isAllChecked.value = shouldCheckAll pageModel.rv?.commonAdapter()?.notifyDataSetChanged() From dfddf646f5274d1ead4766e6bf51cdff5ef2de19 Mon Sep 17 00:00:00 2001 From: YANGJIANKUAN Date: Fri, 16 Jan 2026 17:53:46 +0800 Subject: [PATCH 9/9] =?UTF-8?q?feat:=20=E5=9B=BD=E9=99=85=E5=87=BA?= =?UTF-8?q?=E6=B8=AF=20=E5=87=BA=E6=B8=AF=E4=BB=93=E5=BA=93=20=E5=87=BA?= =?UTF-8?q?=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lukouguoji/module_base/http/net/Api.kt | 7 ++++ .../gjc/activity/IntExpStorageUseActivity.kt | 32 +++++++++++++++++ .../viewModel/IntExpStorageUseViewModel.kt | 35 +++++++++++++------ .../layout/activity_int_exp_storage_use.xml | 2 +- 4 files changed, 64 insertions(+), 12 deletions(-) diff --git a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt index 70237aa..80f8b5d 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt @@ -825,6 +825,13 @@ interface Api { @POST("IntExpStorageUse/modifyStorage") suspend fun modifyIntExpStorage(@Body data: RequestBody): BaseResultBean + /** + * 国际出港库位操作-出库 + * 接口路径: /IntExpStorageUse/outStorage + */ + @POST("IntExpStorageUse/outStorage") + suspend fun outIntExpStorage(@Body data: RequestBody): BaseResultBean + /** * 国际出港仓库-分页查询 * 接口路径: /IntExpStorageUse/pageQuery diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt index 15d2c56..01dc11f 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt @@ -3,6 +3,7 @@ package com.lukouguoji.gjc.activity import android.app.Activity import android.content.Intent import android.os.Bundle +import androidx.appcompat.app.AlertDialog import com.alibaba.android.arouter.facade.annotation.Route import com.lukouguoji.gjc.R import com.lukouguoji.gjc.databinding.ActivityIntExpStorageUseBinding @@ -119,6 +120,37 @@ class IntExpStorageUseActivity : }.show(this) } + /** + * 显示出库二次确认对话框 + */ + fun showOutStorageDialog() { + val list = viewModel.pageModel.rv?.commonAdapter()?.items as? List<*> ?: return + val allItems = list.filterIsInstance() + + // 收集所有选中的子列表项(库位) + val selectedStorageUseList = mutableListOf() + allItems.forEach { maWb -> + maWb.storageUseList?.filter { it.isSelected }?.let { selectedStorageUseList.addAll(it) } + } + + // 校验:必须至少选中一个库位 + if (selectedStorageUseList.isEmpty()) { + showToast("请选择要出库的库位") + return + } + + // 显示二次确认对话框 + AlertDialog.Builder(this) + .setTitle("出库确认") + .setMessage("确定要将选中的 ${selectedStorageUseList.size} 个库位执行出库操作吗?") + .setPositiveButton("确定") { _, _ -> + // 用户确认后,执行出库操作 + viewModel.performOutStorage(selectedStorageUseList) + } + .setNegativeButton("取消", null) + .show() + } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == Constant.RequestCode.WAYBILL && resultCode == Activity.RESULT_OK) { diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt index cfa3201..9341b4a 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt @@ -207,24 +207,37 @@ class IntExpStorageUseViewModel : BasePageViewModel() { } /** - * 出库操作 + * 出库操作(在Activity中调用,会显示二次确认对话框) */ fun outStorage() { - val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + // 由Activity显示二次确认对话框 + } - // 收集所有选中的子列表项(库位) - val selectedStorageUseList = mutableListOf() - list.forEach { maWb -> - maWb.storageUseList?.filter { it.isSelected }?.let { selectedStorageUseList.addAll(it) } - } - - if (selectedStorageUseList.isEmpty()) { + /** + * 执行出库操作 + * @param selectedStorageList 选中的子列表项(库位) + */ + fun performOutStorage(selectedStorageList: List) { + if (selectedStorageList.isEmpty()) { showToast("请选择要出库的库位") return } - // TODO: 实现出库接口调用 - showToast("出库功能待实现") + // 将选中的子列表项转换为RequestBody + val params = selectedStorageList.toRequestBody() + + launchLoadingCollect({ NetApply.api.outIntExpStorage(params) }) { + onSuccess = { + showToast("出库成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + refresh() // 刷新列表 + } + onFailed = { _, msg -> + showToast(msg.noNull("出库失败")) + } + } } /** diff --git a/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml b/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml index 845de19..553ffbf 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml @@ -234,7 +234,7 @@