From 6073010531ab391037e01da44747385b78b333fc Mon Sep 17 00:00:00 2001 From: YANGJIANKUAN Date: Thu, 4 Dec 2025 18:59:54 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=87=BA=E6=B8=AF=E8=BF=90=E6=8A=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 6 + .../aerologic/ui/fragment/HomeFragment.kt | 13 + .../lukouguoji/module_base/bean/GjcMaWb.kt | 21 +- .../lukouguoji/module_base/common/Constant.kt | 1 + .../lukouguoji/module_base/http/net/Api.kt | 30 ++ .../module_base/router/ARouterConstants.kt | 1 + .../gjc/activity/IntExpArriveActivity.kt | 69 ++++ .../gjc/holder/IntExpArriveViewHolder.kt | 29 ++ .../gjc/viewModel/IntExpArriveViewModel.kt | 174 ++++++++++ .../res/layout/activity_int_exp_arrive.xml | 206 ++++++++++++ .../main/res/layout/item_int_exp_arrive.xml | 318 ++++++++++++++++++ 11 files changed, 866 insertions(+), 2 deletions(-) create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveActivity.kt create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveViewHolder.kt create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt create mode 100644 module_gjc/src/main/res/layout/activity_int_exp_arrive.xml create mode 100644 module_gjc/src/main/res/layout/item_int_exp_arrive.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9bc1d1a..bf4473c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -115,6 +115,12 @@ android:configChanges="orientation|keyboardHidden" android:exported="false" android:screenOrientation="userLandscape" /> + + { + ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE) + .navigation() + } /** * 国际进港 */ @@ -666,6 +671,14 @@ class HomeFragment : Fragment() { ) ) + list.add( + RightMenu( + Constant.AuthName.GjcIntExpArrive, + com.lukouguoji.module_base.R.drawable.img_gjc_banxiangzuzhuang, + "出港运抵" + ) + ) + // list.add( // RightMenu( // Constant.AuthName.GjcWareHouseActivity, 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 f3d062c..7b08c82 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,5 +1,6 @@ package com.lukouguoji.module_base.bean +import androidx.databinding.ObservableBoolean import java.util.Date /** @@ -106,7 +107,15 @@ data class GjcMaWb( var haWbList: List? = null, // 分单列表 var storageUseList: List? = null, // 库位使用列表 var attachList: List? = null // 附件列表 -) +) { + // ==================== UI扩展字段 ==================== + val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态 + + // 兼容现有API的isSelected属性 + var isSelected: Boolean + get() = checked.get() + set(value) = checked.set(value) +} /** * 国际出港分单数据模型 @@ -185,7 +194,15 @@ data class GjcHaWb( var tallyOpId: String? = null, // 理货操作人ID var declareCount: Long? = null, // 申报次数 var activeId: Long? = null // 活动ID -) +) { + // ==================== UI扩展字段 ==================== + val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态 + + // 兼容现有API的isSelected属性 + var isSelected: Boolean + get() = checked.get() + set(value) = checked.set(value) +} /** * 库位使用记录 diff --git a/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt b/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt index c812d2c..5284347 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt @@ -247,6 +247,7 @@ interface Constant { const val GjcIntExpAssembleActivity = "AppIntExpAssemble" //出港组装 const val GjcAssembleAllocateActivity = "AppIntExpAssembleAllocate" //组装分配 const val GjcIntExpOutHandover = "AppIntExpOutHandover" //出库交接 + const val GjcIntExpArrive = "AppIntExpArrive" //出港运抵 /** * 国际进港 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 a778eeb..ebcc080 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 @@ -558,6 +558,36 @@ interface Api { @POST("IntExpOutHandover/handover") suspend fun completeHandover(@Body data: RequestBody): BaseResultBean + /** + * 国际出港运抵-分页列表 + * 接口路径: /IntExpArrive/pageQuery + */ + @POST("IntExpArrive/pageQuery") + suspend fun getIntExpArriveList(@Body data: RequestBody): BaseListBean + + /** + * 国际出港运抵-分页合计 + * 接口路径: /IntExpArrive/pageQueryTotal + */ + @POST("IntExpArrive/pageQueryTotal") + suspend fun getIntExpArriveTotal(@Body data: RequestBody): BaseResultBean + + /** + * 国际出港运抵-重置运抵申报状态 + * 接口路径: /IntExpArrive/resetDeclare + * @param data 请求参数:选中的运单列表 + */ + @POST("IntExpArrive/resetDeclare") + suspend fun resetArriveDeclare(@Body data: RequestBody): BaseResultBean + + /** + * 国际出港运抵-运抵申报(分单+主单) + * 接口路径: /IntExpArrive/declare + * @param data 请求参数:选中的运单列表 + */ + @POST("IntExpArrive/declare") + suspend fun arriveDeclare(@Body data: RequestBody): BaseResultBean + /** * 国际出港移库-分页查询 * 接口路径: /IntExpMove/pageQuery diff --git a/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt b/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt index 1f7420c..4bb422b 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt @@ -143,6 +143,7 @@ object ARouterConstants { const val ACTIVITY_URL_INT_EXP_MOVE = "/gjc/IntExpMoveActivity" //国际出港 出港移库 const val ACTIVITY_URL_GJC_ASSEMBLE_ALLOCATE = "/gjc/GjcAssembleAllocateActivity" //国际出港 组装分配 const val ACTIVITY_URL_INT_EXP_OUT_HANDOVER = "/gjc/IntExpOutHandoverActivity" //国际出港 出库交接 + const val ACTIVITY_URL_INT_EXP_ARRIVE = "/gjc/IntExpArriveActivity" //国际出港 出港运抵 ///////////////// 国际进港模块 /** diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveActivity.kt new file mode 100644 index 0000000..724154c --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveActivity.kt @@ -0,0 +1,69 @@ +package com.lukouguoji.gjc.activity + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import com.alibaba.android.arouter.facade.annotation.Route +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityIntExpArriveBinding +import com.lukouguoji.gjc.viewModel.IntExpArriveViewModel +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.addOnItemClickListener +import com.lukouguoji.module_base.router.ARouterConstants + +/** + * 国际出港-出港运抵页面 + */ +@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE) +class IntExpArriveActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_exp_arrive + override fun viewModelClass() = IntExpArriveViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("出港运抵") + binding.viewModel = viewModel + + // 观察全选状态,更新图标透明度 + viewModel.isAllChecked.observe(this) { isAllChecked -> + binding.checkIcon.alpha = if (isAllChecked) 1.0f else 0.5f + } + + // 绑定分页 + viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this) + + // 设置item点击监听 + binding.rv.addOnItemClickListener(viewModel) + + // 监听刷新事件 + FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) { + viewModel.refresh() + } + + // 初始加载数据 + viewModel.refresh() + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + when (requestCode) { + Constant.RequestCode.WAYBILL -> { + if (resultCode == Activity.RESULT_OK) { + viewModel.waybillNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT) + viewModel.searchClick() + } + } + Constant.RequestCode.CODE -> { + if (resultCode == Activity.RESULT_OK) { + viewModel.hno.value = data?.getStringExtra(Constant.Result.CODED_CONTENT) + viewModel.searchClick() + } + } + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveViewHolder.kt new file mode 100644 index 0000000..3d57bdd --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveViewHolder.kt @@ -0,0 +1,29 @@ +package com.lukouguoji.gjc.holder + +import android.view.View +import com.lukouguoji.gjc.databinding.ItemIntExpArriveBinding +import com.lukouguoji.module_base.base.BaseViewHolder +import com.lukouguoji.module_base.bean.GjcMaWb + +/** + * 国际出港-出港运抵 列表项ViewHolder + */ +class IntExpArriveViewHolder(view: View) : + BaseViewHolder(view) { + + override fun onBind(item: Any?, position: Int) { + val bean = getItemBean(item) ?: return + binding.bean = bean + binding.position = position + binding.executePendingBindings() + + // 添加图标点击事件 - 切换选择状态 + binding.ivIcon.setOnClickListener { + // 反转checked状态 + bean.checked.set(!bean.checked.get()) + + // 立即更新UI(图片自动切换) + binding.executePendingBindings() + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt new file mode 100644 index 0000000..21d8589 --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt @@ -0,0 +1,174 @@ +package com.lukouguoji.gjc.viewModel + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.holder.IntExpArriveViewHolder +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.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 kotlinx.coroutines.launch + +/** + * 国际出港-出港运抵 ViewModel + */ +class IntExpArriveViewModel : BasePageViewModel() { + + // ========== 搜索条件 ========== + val flightDate = MutableLiveData("") // 航班日期 + val flightNo = MutableLiveData("") // 航班号 + val waybillNo = MutableLiveData("") // 运单号 + val hno = MutableLiveData("") // 分单号 + + // ========== 统计信息 ========== + val totalCount = MutableLiveData("0") // 合计票数 + val totalPc = MutableLiveData("0") // 总件数 + val totalWeight = MutableLiveData("0") // 总重量 + + // ========== 全选状态 ========== + val isAllChecked = MutableLiveData(false) + + init { + // 监听全选状态,自动更新所有列表项 + isAllChecked.observeForever { checked -> + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return@observeForever + list.forEach { it.checked.set(checked) } + pageModel.rv?.commonAdapter()?.notifyDataSetChanged() + } + } + + // ========== 适配器配置 ========== + val itemViewHolder = IntExpArriveViewHolder::class.java + val itemLayoutId = R.layout.item_int_exp_arrive + + /** + * 搜索按钮点击 + */ + fun searchClick() { + refresh() + } + + /** + * 全选按钮点击 (切换全选状态) + */ + fun checkAllClick() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + + // 切换全选状态 + val shouldCheckAll = !isAllChecked.value!! + list.forEach { it.checked.set(shouldCheckAll) } + isAllChecked.value = shouldCheckAll + + pageModel.rv?.commonAdapter()?.notifyDataSetChanged() + } + + /** + * 扫码运单号 + */ + fun scanWaybill() { + ScanModel.startScan(getTopActivity(), Constant.RequestCode.WAYBILL) + } + + /** + * 扫码分单号 + */ + fun scanHaWb() { + ScanModel.startScan(getTopActivity(), Constant.RequestCode.CODE) + } + + /** + * 状态重置 + */ + fun resetDeclareClick() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + val selectedItems = list.filter { it.isSelected } + + if (selectedItems.isEmpty()) { + showToast("请选择要重置的运单") + return + } + + val requestData = mapOf("maWbList" to selectedItems).toRequestBody() + + launchLoadingCollect({ NetApply.api.resetArriveDeclare(requestData) }) { + onSuccess = { + showToast("状态重置成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + refresh() + } + } + } + + /** + * 运抵申报 + */ + fun arriveReportClick() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + val selectedItems = list.filter { it.isSelected } + + if (selectedItems.isEmpty()) { + showToast("请选择要申报的运单") + return + } + + val requestData = mapOf("maWbList" to selectedItems).toRequestBody() + + launchLoadingCollect({ NetApply.api.arriveDeclare(requestData) }) { + onSuccess = { + showToast("运抵申报成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + refresh() + } + } + } + + /** + * 获取数据 (重写BasePageViewModel) + */ + override fun getData() { + // 构建搜索条件 + val filterParams = mapOf( + "fdate" to flightDate.value?.ifEmpty { null }, + "fno" to flightNo.value?.ifEmpty { null }, + "likeNo" to waybillNo.value?.ifEmpty { null }, + "hno" to hno.value?.ifEmpty { null } + ) + + // 列表参数 (含分页) + val listParams = (filterParams + mapOf( + "pageNum" to pageModel.page, + "pageSize" to pageModel.limit + )).toRequestBody() + + // 统计参数 (无分页) + val totalParams = filterParams.toRequestBody() + + // 获取列表 (带Loading) + launchLoadingCollect({ NetApply.api.getIntExpArriveList(listParams) }) { + onSuccess = { pageModel.handleListBean(it) } + } + + // 获取统计信息 (后台请求) + launchCollect({ NetApply.api.getIntExpArriveTotal(totalParams) }) { + onSuccess = { result -> + val data = result.data + totalCount.value = (data?.wbNumber ?: 0).toString() + totalPc.value = (data?.totalPc ?: 0).toString() + totalWeight.value = (data?.totalWeight ?: 0.0).toString() + } + } + } +} diff --git a/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml b/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml new file mode 100644 index 0000000..cf47bfa --- /dev/null +++ b/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_int_exp_arrive.xml b/module_gjc/src/main/res/layout/item_int_exp_arrive.xml new file mode 100644 index 0000000..dcb764f --- /dev/null +++ b/module_gjc/src/main/res/layout/item_int_exp_arrive.xml @@ -0,0 +1,318 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +