diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 43669c2..36cc6f9 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -121,6 +121,12 @@
android:configChanges="orientation|keyboardHidden"
android:exported="false"
android:screenOrientation="userLandscape" />
+
+
{
+ ARouter.getInstance()
+ .build(ARouterConstants.ACTIVITY_URL_INT_EXP_TALLY)
+ .navigation()
+ }
// 出港运抵
Constant.AuthName.GjcIntExpArrive -> {
ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE)
@@ -703,6 +709,14 @@ class HomeFragment : Fragment() {
)
)
+ list.add(
+ RightMenu(
+ Constant.AuthName.GjcIntExpTally,
+ com.lukouguoji.module_base.R.drawable.img_gjc_banxiangzuzhuang,
+ "出港理货"
+ )
+ )
+
list.add(
RightMenu(
Constant.AuthName.GjcIntExpArrive,
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 938ee22..6bdc902 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
@@ -248,6 +248,7 @@ interface Constant {
const val GjcAssembleAllocateActivity = "AppIntExpAssembleAllocate" //组装分配
const val GjcIntExpOutHandover = "AppIntExpOutHandover" //出库交接
const val GjcIntExpLoad = "AppIntExpLoad" //出港装载
+ const val GjcIntExpTally = "AppIntExpTally" //出港理货
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 20a680c..2f9388e 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
@@ -669,6 +669,38 @@ interface Api {
@POST("IntExpArrive/declare")
suspend fun arriveDeclare(@Body data: RequestBody): BaseResultBean
+ /**
+ * 国际出港-出港理货-列表查询
+ * 接口路径: /IntExpTally/pageQuery
+ * 返回: PageInfo
+ */
+ @POST("IntExpTally/pageQuery")
+ suspend fun getIntExpTallyList(@Body data: RequestBody): BaseListBean
+
+ /**
+ * 国际出港-出港理货-统计查询
+ * 接口路径: /IntExpTally/pageQueryTotal
+ * 返回: ManifestTotalDto(合计票数、总件数、总重量)
+ */
+ @POST("IntExpTally/pageQueryTotal")
+ suspend fun getIntExpTallyTotal(@Body data: RequestBody): BaseResultBean
+
+ /**
+ * 国际出港-出港理货-理货申报
+ * 接口路径: /IntExpTally/declare
+ * @param data 请求参数:选中的GjcMaWb列表
+ */
+ @POST("IntExpTally/declare")
+ suspend fun declareTally(@Body data: RequestBody): BaseResultBean
+
+ /**
+ * 国际出港-出港理货-状态重置
+ * 接口路径: /IntExpTally/resetDeclare
+ * @param data 请求参数:选中的GjcMaWb列表
+ */
+ @POST("IntExpTally/resetDeclare")
+ suspend fun resetTallyDeclare(@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 cbf9752..5fda4ff 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
@@ -144,6 +144,7 @@ object ARouterConstants {
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_LOAD = "/gjc/IntExpLoadActivity" //国际出港 出港装载
+ const val ACTIVITY_URL_INT_EXP_TALLY = "/gjc/IntExpTallyActivity" //国际出港 出港理货
const val ACTIVITY_URL_INT_EXP_ARRIVE = "/gjc/IntExpArriveActivity" //国际出港 出港运抵
///////////////// 国际进港模块
diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpTallyActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpTallyActivity.kt
new file mode 100644
index 0000000..792d12f
--- /dev/null
+++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpTallyActivity.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.ActivityIntExpTallyBinding
+import com.lukouguoji.gjc.viewModel.IntExpTallyViewModel
+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.interfaces.IOnItemClickListener
+import com.lukouguoji.module_base.ktx.addOnItemClickListener
+import com.lukouguoji.module_base.router.ARouterConstants
+
+/**
+ * 国际出港-出港理货
+ */
+@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_TALLY)
+class IntExpTallyActivity :
+ BaseBindingActivity() {
+
+ override fun layoutId() = R.layout.activity_int_exp_tally
+ override fun viewModelClass() = IntExpTallyViewModel::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)
+ if (resultCode == Activity.RESULT_OK) {
+ val codedContent = data?.getStringExtra(Constant.Result.CODED_CONTENT) ?: return
+ when (requestCode) {
+ Constant.RequestCode.WAYBILL -> { // 运单号
+ viewModel.waybillNo.value = codedContent
+ viewModel.searchClick()
+ }
+ Constant.RequestCode.CODE -> { // 分单号
+ viewModel.houseWaybillNo.value = codedContent
+ viewModel.searchClick()
+ }
+ }
+ }
+ }
+}
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
new file mode 100644
index 0000000..a45ccd7
--- /dev/null
+++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpTallyViewHolder.kt
@@ -0,0 +1,26 @@
+package com.lukouguoji.gjc.holder
+
+import android.view.View
+import com.lukouguoji.gjc.databinding.ItemIntExpTallyBinding
+import com.lukouguoji.module_base.base.BaseViewHolder
+import com.lukouguoji.module_base.bean.GjcMaWb
+
+/**
+ * 国际出港-出港理货 ViewHolder
+ */
+class IntExpTallyViewHolder(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 {
+ bean.checked.set(!bean.checked.get())
+ binding.executePendingBindings()
+ }
+ }
+}
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
new file mode 100644
index 0000000..fbc1af5
--- /dev/null
+++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpTallyViewModel.kt
@@ -0,0 +1,187 @@
+package com.lukouguoji.gjc.viewModel
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.viewModelScope
+import com.lukouguoji.gjc.R
+import com.lukouguoji.gjc.holder.IntExpTallyViewHolder
+import com.lukouguoji.module_base.base.BasePageViewModel
+import com.lukouguoji.module_base.bean.GjcCheckInPage
+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 IntExpTallyViewModel : BasePageViewModel() {
+
+ // ========== 搜索条件 ==========
+ val flightDate = MutableLiveData("") // 航班日期
+ val flightNo = MutableLiveData("") // 航班号
+ val waybillNo = MutableLiveData("") // 运单号
+ val houseWaybillNo = 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 = IntExpTallyViewHolder::class.java
+ val itemLayoutId = R.layout.item_int_exp_tally
+
+ /**
+ * 搜索按钮点击
+ */
+ 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 scanHouseWaybill() {
+ ScanModel.startScan(getTopActivity(), Constant.RequestCode.CODE)
+ }
+
+ /**
+ * 状态重置 (批量操作)
+ */
+ fun resetDeclare() {
+ val list = pageModel.rv?.commonAdapter()?.items as? List ?: return
+ val selectedItems = list.filter { it.isSelected }
+
+ if (selectedItems.isEmpty()) {
+ showToast("请选择要重置的记录")
+ return
+ }
+
+ val requestData = selectedItems.toRequestBody()
+
+ launchLoadingCollect({ NetApply.api.resetTallyDeclare(requestData) }) {
+ onSuccess = {
+ showToast("状态重置成功")
+ viewModelScope.launch {
+ FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh")
+ }
+ refresh()
+ }
+ }
+ }
+
+ /**
+ * 理货申报 (批量操作)
+ */
+ fun declareTally() {
+ val list = pageModel.rv?.commonAdapter()?.items as? List ?: return
+ val selectedItems = list.filter { it.isSelected }
+
+ if (selectedItems.isEmpty()) {
+ showToast("请选择要理货的记录")
+ return
+ }
+
+ val requestData = selectedItems.toRequestBody()
+
+ launchLoadingCollect({ NetApply.api.declareTally(requestData) }) {
+ onSuccess = {
+ showToast("理货申报成功")
+ viewModelScope.launch {
+ FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh")
+ }
+ refresh()
+ }
+ }
+ }
+
+ /**
+ * 删除申报 (批量操作)
+ * TODO: 待实现
+ */
+ fun deleteTally() {
+ // 暂不实现,预留接口
+ }
+
+ /**
+ * 获取数据 (重写BasePageViewModel)
+ */
+ override fun getData() {
+ // 构建查询参数对象
+ val pageParams = GjcCheckInPage(
+ fdate = flightDate.value?.ifEmpty { null },
+ fno = flightNo.value?.ifEmpty { null },
+ no = waybillNo.value?.ifEmpty { null },
+ hno = houseWaybillNo.value?.ifEmpty { null },
+ pageNum = pageModel.page,
+ pageSize = pageModel.limit
+ )
+
+ // 列表参数 (含分页)
+ val listParams = pageParams.toRequestBody()
+
+ // 统计参数 (无分页)
+ val totalParams = GjcCheckInPage(
+ fdate = flightDate.value?.ifEmpty { null },
+ fno = flightNo.value?.ifEmpty { null },
+ no = waybillNo.value?.ifEmpty { null },
+ hno = houseWaybillNo.value?.ifEmpty { null }
+ ).toRequestBody()
+
+ // 获取列表 (带Loading)
+ launchLoadingCollect({ NetApply.api.getIntExpTallyList(listParams) }) {
+ onSuccess = { pageModel.handleListBean(it) }
+ }
+
+ // 获取统计信息 (后台请求,不阻塞列表)
+ launchCollect({ NetApply.api.getIntExpTallyTotal(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_tally.xml b/module_gjc/src/main/res/layout/activity_int_exp_tally.xml
new file mode 100644
index 0000000..9bbd0c0
--- /dev/null
+++ b/module_gjc/src/main/res/layout/activity_int_exp_tally.xml
@@ -0,0 +1,215 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/module_gjc/src/main/res/layout/item_int_exp_tally.xml b/module_gjc/src/main/res/layout/item_int_exp_tally.xml
new file mode 100644
index 0000000..6aa6dda
--- /dev/null
+++ b/module_gjc/src/main/res/layout/item_int_exp_tally.xml
@@ -0,0 +1,256 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+