diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 6d60244..1f396c9 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -55,7 +55,10 @@
"Bash(xargs:*)",
"Bash(unzip:*)",
"WebFetch(domain:gainscha.github.io)",
- "WebFetch(domain:m.gainscha.com)"
+ "WebFetch(domain:m.gainscha.com)",
+ "Bash(git add:*)",
+ "Bash(git commit:*)",
+ "WebFetch(domain:support.claude.com)"
],
"deny": [],
"ask": []
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b4ac4f6..853ae5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -419,6 +419,27 @@
android:exported="false"
android:screenOrientation="userLandscape" />
+
+
+
+
+
+
+
+
+
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 8eb01b8..8608ae8 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
@@ -451,6 +451,18 @@ class HomeFragment : Fragment() {
.navigation()
}
+ // 进港仓库
+ Constant.AuthName.GjjWareHouseActivity -> {
+ ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_GJJ_WARE_HOUSE)
+ .navigation()
+ }
+
+ // 提取记录
+ Constant.AuthName.IntImpPickUpRecord -> {
+ ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_INT_IMP_PICK_UP_RECORD)
+ .navigation()
+ }
+
/**
* 航班查询
*/
@@ -800,6 +812,20 @@ class HomeFragment : Fragment() {
"理货报告"
)
)
+ list.add(
+ RightMenu(
+ Constant.AuthName.GjjWareHouseActivity,
+ R.mipmap.gnj_cang_ku_icon,
+ "进港仓库"
+ )
+ )
+ list.add(
+ RightMenu(
+ Constant.AuthName.IntImpPickUpRecord,
+ R.mipmap.gnj_cang_ku_icon,
+ "提取记录"
+ )
+ )
}
Constant.AuthName.Flight -> {
diff --git a/module_base/src/main/java/com/lukouguoji/module_base/LoginActivity.kt b/module_base/src/main/java/com/lukouguoji/module_base/LoginActivity.kt
index bb22afa..0d6b880 100644
--- a/module_base/src/main/java/com/lukouguoji/module_base/LoginActivity.kt
+++ b/module_base/src/main/java/com/lukouguoji/module_base/LoginActivity.kt
@@ -41,7 +41,7 @@ import me.jessyan.autosize.internal.CustomAdapt
* ========== 开发调试开关 ==========
* TODO: 正式发布前务必设置为 false
*/
-private const val DEV_AUTO_LOGIN = false // 自动登录开关
+private const val DEV_AUTO_LOGIN = true // 自动登录开关
@Route(path = ARouterConstants.ACTIVITY_URL_LOGIN)
class LoginActivity : BaseActivity(),
diff --git a/module_base/src/main/java/com/lukouguoji/module_base/adapter/SpinnerAdapter.kt b/module_base/src/main/java/com/lukouguoji/module_base/adapter/SpinnerAdapter.kt
index 0add0f7..f5f9eba 100644
--- a/module_base/src/main/java/com/lukouguoji/module_base/adapter/SpinnerAdapter.kt
+++ b/module_base/src/main/java/com/lukouguoji/module_base/adapter/SpinnerAdapter.kt
@@ -49,6 +49,26 @@ fun bindAdapter(
if (hint.isNullOrEmpty()) {
val adapter = ArrayAdapter(spinner.context, layoutId, list)
spinner.adapter = adapter
+ } else if (list.isEmpty()) {
+ // 列表为空时:控件上显示 hint 占位文字(灰色),下拉列表隐藏
+ // 不能用 SpinnerHintAdapter,其 getCount()=0 会导致 Spinner 不渲染
+ val adapter = object : ArrayAdapter(spinner.context, layoutId, listOf(hint)) {
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ val view = super.getView(position, convertView, parent)
+ (view as TextView).setTextColor(context.resources.getColor(R.color.text_gray_l))
+ return view
+ }
+
+ override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
+ // 下拉列表中隐藏 hint 项
+ val view = super.getDropDownView(position, convertView, parent)
+ view.visibility = View.GONE
+ view.layoutParams = ViewGroup.LayoutParams(0, 0)
+ return view
+ }
+ }
+ spinner.adapter = adapter
+ spinner.setSelection(0)
} else {
val containHintList = list + hint
val adapter = SpinnerHintAdapter(spinner.context, layoutId, containHintList)
diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpPickUpRecordBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpPickUpRecordBean.kt
new file mode 100644
index 0000000..59a16d6
--- /dev/null
+++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpPickUpRecordBean.kt
@@ -0,0 +1,37 @@
+package com.lukouguoji.module_base.bean
+
+import androidx.databinding.ObservableBoolean
+import java.io.Serializable
+
+/**
+ * 国际进港提取记录-列表数据Bean
+ * 对应API: IntImpPickUpRecord/pageQuery
+ */
+class IntImpPickUpRecordBean : Serializable {
+ var id: Long = 0 // 主键ID
+ var wbNo: String = "" // 运单号
+ var pc: Int = 0 // 件数
+ var weight: Double = 0.0 // 重量
+ var checkWeight: Double = 0.0 // 计重重量
+ var agentCode: String = "" // 代理人
+ var spCode: String = "" // 特码
+ var serviceFee: Double = 0.0 // 服务费
+ var storageFee: Double = 0.0 // 仓储费
+ var totalAmount: Double = 0.0 // 总金额
+ var pickUpTime: String = "" // 提取时间
+ var pickUpNo: String = "" // 提货编号
+ var infoFee: Double = 0.0 // 信息费
+ var drawFee: Double = 0.0 // 抽单费
+ var coldFee: Double = 0.0 // 冷藏费
+ var forkliftFee: Double = 0.0 // 铲车费
+ var tallyFee: Double = 0.0 // 理货费
+ var operator: String = "" // 办理人
+ var outTime: String = "" // 出库时间
+
+ // ========== UI扩展字段 ==========
+ val checked: ObservableBoolean = ObservableBoolean(false)
+
+ 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 0a0d4d8..29d3206 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
@@ -270,6 +270,7 @@ interface Constant {
const val IntArrAirManifest = "AppIntArrAirManifest" //原始舱单
const val IntImpManifest = "AppIntImpManifest" //进港舱单
const val IntImpTally = "AppIntImpTally" //理货报告
+ const val IntImpPickUpRecord = "AppIntImpPickUpRecord" //提取记录
const val GjjManifestListActivity = "AppIntExpManifest" //舱单
const val GjjTallyListActivity = "AppIntExpTally" //理货
const val GjjGoodsListActivity = "AppIntExpGjjGoods" //货物交接
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 81b5c97..7d44dcc 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
@@ -49,6 +49,7 @@ import com.lukouguoji.module_base.bean.GjjGoodsDetailsBean
import com.lukouguoji.module_base.bean.GjjGoodsTypeBean
import com.lukouguoji.module_base.bean.GjjHandoverRecordBean
import com.lukouguoji.module_base.bean.GjjImportTally
+import com.lukouguoji.module_base.bean.IntImpPickUpRecordBean
import com.lukouguoji.module_base.bean.GjjManifest
import com.lukouguoji.module_base.bean.GjjManifestBean
import com.lukouguoji.module_base.bean.GjjPackTypeBean
@@ -227,6 +228,12 @@ interface Api {
@POST("typeCode/intExp/agentCode")
suspend fun getIntExpAgentList(): DictListBean
+ /**
+ * 获取代理人-国际进港-下拉框
+ */
+ @POST("typeCode/intImp/agentCode")
+ suspend fun getIntImpAgentList(): DictListBean
+
/**
* 获取业务类型---CI:国内进港,CO:国内出港,II:国际进港,IO:国际出港 下拉框
*/
@@ -891,6 +898,76 @@ interface Api {
@GET("typeCode/locationByFlag")
suspend fun getLocationList(@Query("flag") flag: Int): BaseResultBean>
+ /**
+ * 国际进港仓库-分页查询
+ * 接口路径: /IntImpStorageUse/pageQuery
+ */
+ @POST("IntImpStorageUse/pageQuery")
+ suspend fun getIntImpStorageUseList(@Body data: RequestBody): PageInfo
+
+ /**
+ * 国际进港仓库-分页合计
+ * 接口路径: /IntImpStorageUse/pageQueryTotal
+ */
+ @POST("IntImpStorageUse/pageQueryTotal")
+ suspend fun getIntImpStorageUseTotal(@Body data: RequestBody): BaseResultBean
+
+ /**
+ * 国际进港库位操作-清仓
+ * 接口路径: /IntImpStorageUse/updateClear
+ */
+ @POST("IntImpStorageUse/updateClear")
+ suspend fun clearIntImpStorage(@Body data: RequestBody): BaseResultBean
+
+ /**
+ * 国际进港库位操作-修改库位
+ * 接口路径: /IntImpStorageUse/modifyStorage
+ */
+ @POST("IntImpStorageUse/modifyStorage")
+ suspend fun modifyIntImpStorage(@Body data: RequestBody): BaseResultBean
+
+ /**
+ * 国际进港库位操作-出库
+ * 接口路径: /IntImpStorageUse/outStorage
+ */
+ @POST("IntImpStorageUse/outStorage")
+ suspend fun outIntImpStorage(@Body data: RequestBody): BaseResultBean
+
+ /**
+ * 国际进港库位操作-入库
+ * 接口路径: /IntImpStorageUse/inStorage
+ */
+ @POST("IntImpStorageUse/inStorage")
+ suspend fun inIntImpStorage(@Body data: RequestBody): BaseResultBean
+
+ /**
+ * 国际进港提取记录-分页查询
+ * 接口路径: /IntImpPickUpRecord/pageQuery
+ */
+ @POST("IntImpPickUpRecord/pageQuery")
+ suspend fun getIntImpPickUpRecordList(@Body data: RequestBody): PageInfo
+
+ /**
+ * 国际进港提取记录-分页合计
+ * 接口路径: /IntImpPickUpRecord/pageQueryTotal
+ */
+ @POST("IntImpPickUpRecord/pageQueryTotal")
+ suspend fun getIntImpPickUpRecordTotal(@Body data: RequestBody): BaseResultBean
+
+ /**
+ * 国际进港提取记录-清除提货
+ * 接口路径: /IntImpPickUpRecord/clearPickUp
+ */
+ @POST("IntImpPickUpRecord/clearPickUp")
+ suspend fun clearIntImpPickUp(@Body data: RequestBody): BaseResultBean
+
+ /**
+ * 国际进港提取记录-详情
+ * 接口路径: /IntImpPickUpRecord/getDetails
+ */
+ @POST("IntImpPickUpRecord/getDetails")
+ suspend fun getIntImpPickUpRecordDetails(@Body data: RequestBody): BaseResultBean
+
/**
* 国际出港待计重-分页搜索
* 接口路径: /IntExpCheckIn/pageQuery
@@ -1634,7 +1711,7 @@ interface Api {
* 分页查询国际进港电报
*/
@POST("IntImpMsg/pageQuery")
- suspend fun getIntImpMsgList(@Body data: RequestBody): BaseResultBean>
+ suspend fun getIntImpMsgList(@Body data: RequestBody): PageInfo
/**
* 批量生成电报
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 6bfea93..f893b95 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
@@ -160,6 +160,7 @@ object ARouterConstants {
const val ACTIVITY_URL_GJJ_WARE_HOUSE_INFO = "/gjj/GjjWareHouseInfoActivity" //国际进港模块 仓库详情
const val ACTIVITY_URL_GJJ_CHU_KU_LIST = "/gjj/GjjChuKuListActivity" //国际进港 出库
+ const val ACTIVITY_URL_INT_IMP_PICK_UP_RECORD = "/gjj/IntImpPickUpRecordActivity" //国际进港 提取记录
const val ACTIVITY_URL_GJJ_QUERY_LIST = "/gjj/GjjQueryListActivity" //国际进港 查询 列表
const val ACTIVITY_URL_GJJ_QUERY_INFO = "/gjj/GnjQueryInfoActivity" //国际进港 查询 详情
diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/GjjWareHouseActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/GjjWareHouseActivity.kt
index d531c2a..6152f91 100644
--- a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/GjjWareHouseActivity.kt
+++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/GjjWareHouseActivity.kt
@@ -29,7 +29,7 @@ import com.scwang.smart.refresh.layout.api.RefreshLayout
import java.text.SimpleDateFormat
import java.util.*
-@Route(path = ARouterConstants.ACTIVITY_URL_GJJ_WARE_HOUSE)
+//@Route(path = ARouterConstants.ACTIVITY_URL_GJJ_WARE_HOUSE)
class GjjWareHouseActivity : BaseActivity(), View.OnClickListener {
private lateinit var viewModel: GjjWareHouseListViewModel
private val currentTitleName = "国际进港仓库管理"
diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpPickUpRecordActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpPickUpRecordActivity.kt
new file mode 100644
index 0000000..6ab6a71
--- /dev/null
+++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpPickUpRecordActivity.kt
@@ -0,0 +1,88 @@
+package com.lukouguoji.gjj.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.gjj.R
+import com.lukouguoji.gjj.databinding.ActivityIntImpPickUpRecordBinding
+import com.lukouguoji.gjj.viewModel.IntImpPickUpRecordViewModel
+import com.lukouguoji.module_base.base.BaseBindingActivity
+import com.lukouguoji.module_base.bean.IntImpPickUpRecordBean
+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
+
+/**
+ * 国际进港-提取记录
+ */
+@Route(path = ARouterConstants.ACTIVITY_URL_INT_IMP_PICK_UP_RECORD)
+class IntImpPickUpRecordActivity :
+ BaseBindingActivity() {
+
+ override fun layoutId() = R.layout.activity_int_imp_pick_up_record
+ override fun viewModelClass() = IntImpPickUpRecordViewModel::class.java
+
+ override fun initOnCreate(savedInstanceState: Bundle?) {
+ setBackArrow("国际进港提取记录")
+ binding.viewModel = viewModel
+ binding.activity = this
+
+ // 观察全选状态,更新图标透明度
+ viewModel.isAllChecked.observe(this) { isAllChecked ->
+ binding.checkIcon.alpha = if (isAllChecked) 1.0f else 0.5f
+ }
+
+ // 绑定分页
+ viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this)
+
+ // 监听刷新事件
+ FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) {
+ viewModel.refresh()
+ }
+
+ // 初始化下拉列表
+ viewModel.initAgentList()
+ viewModel.initSpecialCodeList()
+
+ // 初始加载数据
+ viewModel.refresh()
+ }
+
+ /**
+ * 清除提货操作
+ */
+ fun clearPickUp() {
+ val list = viewModel.pageModel.rv?.commonAdapter()?.items as? List<*> ?: return
+ val allItems = list.filterIsInstance()
+
+ val selectedItems = allItems.filter { it.isSelected }
+
+ if (selectedItems.isEmpty()) {
+ showToast("请选择要清除提货的记录")
+ return
+ }
+
+ AlertDialog.Builder(this)
+ .setTitle("清除提货确认")
+ .setMessage("确定要清除选中的 ${selectedItems.size} 条提货记录吗?")
+ .setPositiveButton("确定") { _, _ ->
+ viewModel.clearPickUp(selectedItems)
+ }
+ .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) {
+ viewModel.wbNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT)
+ viewModel.searchClick()
+ }
+ }
+}
diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpPickUpRecordDetailsActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpPickUpRecordDetailsActivity.kt
new file mode 100644
index 0000000..0b9344b
--- /dev/null
+++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpPickUpRecordDetailsActivity.kt
@@ -0,0 +1,35 @@
+package com.lukouguoji.gjj.activity
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import com.lukouguoji.gjj.R
+import com.lukouguoji.gjj.databinding.ActivityIntImpPickUpRecordDetailsBinding
+import com.lukouguoji.gjj.viewModel.IntImpPickUpRecordDetailsViewModel
+import com.lukouguoji.module_base.base.BaseBindingActivity
+import com.lukouguoji.module_base.common.Constant
+
+/**
+ * 国际进港-提取详情
+ */
+class IntImpPickUpRecordDetailsActivity :
+ BaseBindingActivity() {
+
+ override fun layoutId() = R.layout.activity_int_imp_pick_up_record_details
+ override fun viewModelClass() = IntImpPickUpRecordDetailsViewModel::class.java
+
+ override fun initOnCreate(savedInstanceState: Bundle?) {
+ setBackArrow("国际进港提取详情")
+ binding.viewModel = viewModel
+ viewModel.initOnCreated(intent)
+ }
+
+ companion object {
+ @JvmStatic
+ fun start(context: Context, id: Long) {
+ val starter = Intent(context, IntImpPickUpRecordDetailsActivity::class.java)
+ .putExtra(Constant.Key.ID, id)
+ context.startActivity(starter)
+ }
+ }
+}
diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpStorageUseActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpStorageUseActivity.kt
new file mode 100644
index 0000000..4c467d1
--- /dev/null
+++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpStorageUseActivity.kt
@@ -0,0 +1,178 @@
+package com.lukouguoji.gjj.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.gjj.R
+import com.lukouguoji.gjj.databinding.ActivityIntImpStorageUseBinding
+import com.lukouguoji.gjj.dialog.IntImpMoveClearDialogModel
+import com.lukouguoji.gjj.dialog.IntImpModifyStorageDialogModel
+import com.lukouguoji.gjj.dialog.IntImpInStorageDialogModel
+import com.lukouguoji.gjj.viewModel.IntImpStorageUseViewModel
+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
+
+/**
+ * 国际进港-仓库
+ */
+@Route(path = ARouterConstants.ACTIVITY_URL_GJJ_WARE_HOUSE)
+class IntImpStorageUseActivity :
+ BaseBindingActivity() {
+
+ override fun layoutId() = R.layout.activity_int_imp_storage_use
+ override fun viewModelClass() = IntImpStorageUseViewModel::class.java
+
+ override fun initOnCreate(savedInstanceState: Bundle?) {
+ setBackArrow("国际进港仓库")
+ binding.viewModel = viewModel
+ binding.activity = this
+
+ // 观察全选状态,更新图标透明度
+ viewModel.isAllChecked.observe(this) { isAllChecked ->
+ binding.checkIcon.alpha = if (isAllChecked) 1.0f else 0.5f
+ }
+
+ // 绑定分页
+ viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this)
+
+ // 监听刷新事件
+ FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) {
+ viewModel.refresh()
+ }
+
+ // 初始加载数据
+ viewModel.refresh()
+ }
+
+ /**
+ * 显示清仓操作对话框
+ */
+ fun showClearDialog() {
+ val list = viewModel.pageModel.rv?.commonAdapter()?.items as? List<*> ?: return
+ val allItems = list.filterIsInstance()
+
+ val maWbListForClear = allItems.mapNotNull { maWb ->
+ val selectedStorageList = maWb.storageUseList?.filter { it.isSelected } ?: emptyList()
+
+ if (selectedStorageList.isNotEmpty() || maWb.isSelected) {
+ maWb.copy(storageUseList = selectedStorageList)
+ } else {
+ null
+ }
+ }
+
+ if (maWbListForClear.isEmpty()) {
+ showToast("请至少选择一个库位")
+ return
+ }
+
+ IntImpMoveClearDialogModel { dialog ->
+ val clearNormal = dialog.clearNormal.value ?: ""
+ 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]
+
+ IntImpModifyStorageDialogModel { dialog ->
+ val locationName = dialog.locationName
+ val locationId = dialog.locationId
+ viewModel.performModifyStorage(locationName, locationId, selectedStorage)
+ }.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()
+ }
+
+ /**
+ * 显示入库操作对话框
+ */
+ fun showInStorageDialog() {
+ val list = viewModel.pageModel.rv?.commonAdapter()?.items as? List<*> ?: return
+ val allItems = list.filterIsInstance()
+
+ val maWbListForInStorage = allItems.mapNotNull { maWb ->
+ val selectedStorageList = maWb.storageUseList?.filter { it.isSelected } ?: emptyList()
+
+ if (selectedStorageList.isNotEmpty() || maWb.isSelected) {
+ maWb.copy(storageUseList = selectedStorageList)
+ } else {
+ null
+ }
+ }
+
+ if (maWbListForInStorage.isEmpty()) {
+ showToast("请至少选择一个单据")
+ return
+ }
+
+ IntImpInStorageDialogModel { dialog ->
+ val locationName = dialog.locationName
+ val locationId = dialog.locationId
+ viewModel.performInStorage(locationName, locationId, maWbListForInStorage)
+ }.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) {
+ viewModel.wbNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT)
+ viewModel.searchClick()
+ }
+ }
+}
diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpInStorageDialogModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpInStorageDialogModel.kt
new file mode 100644
index 0000000..a6211db
--- /dev/null
+++ b/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpInStorageDialogModel.kt
@@ -0,0 +1,74 @@
+package com.lukouguoji.gjj.dialog
+
+import android.content.Context
+import androidx.lifecycle.MutableLiveData
+import com.lukouguoji.gjj.R
+import com.lukouguoji.gjj.databinding.DialogIntImpInStorageBinding
+import com.lukouguoji.module_base.base.BaseDialogModel
+import com.lukouguoji.module_base.http.net.NetApply
+import com.lukouguoji.module_base.ktx.launchCollect
+import com.lukouguoji.module_base.ktx.showToast
+import com.lukouguoji.module_base.ktx.verifyNullOrEmpty
+import dev.utils.app.info.KeyValue
+
+/**
+ * 国际进港仓库 - 入库操作对话框
+ */
+class IntImpInStorageDialogModel(
+ private val callback: (IntImpInStorageDialogModel) -> Unit
+) : BaseDialogModel(DIALOG_TYPE_CENTER) {
+
+ // 库位列表
+ val locationList = MutableLiveData>()
+
+ // 选中的库位(存储的是code)
+ val selectedLocationCode = MutableLiveData("")
+
+ // 库位ID (后端需要的code)
+ var locationId: String = ""
+
+ // 库位名称 (后端需要的name)
+ var locationName: String = ""
+
+ override fun layoutId(): Int {
+ return R.layout.dialog_int_imp_in_storage
+ }
+
+ override fun onDialogCreated(context: Context) {
+ binding.model = this
+ loadLocationList()
+
+ // 监听选择变化,更新locationId和locationName
+ selectedLocationCode.observeForever { code ->
+ val selectedItem = locationList.value?.find { it.value == code }
+ locationId = selectedItem?.value ?: ""
+ locationName = selectedItem?.key ?: ""
+ }
+ }
+
+ /**
+ * 加载库位列表
+ */
+ private fun loadLocationList() {
+ launchCollect({ NetApply.api.getLocationList(flag = 4) }) {
+ onSuccess = { result ->
+ val list = result.data?.map { it.toKeyValue() } ?: emptyList()
+ locationList.value = list
+ }
+ onFailed = { _, msg ->
+ showToast(msg ?: "加载库位列表失败")
+ }
+ }
+ }
+
+ /**
+ * 保存按钮点击
+ */
+ fun onSaveClick() {
+ if (selectedLocationCode.value.verifyNullOrEmpty("请选择库位")) {
+ return
+ }
+ dismiss()
+ callback(this)
+ }
+}
diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpModifyStorageDialogModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpModifyStorageDialogModel.kt
new file mode 100644
index 0000000..092c156
--- /dev/null
+++ b/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpModifyStorageDialogModel.kt
@@ -0,0 +1,74 @@
+package com.lukouguoji.gjj.dialog
+
+import android.content.Context
+import androidx.lifecycle.MutableLiveData
+import com.lukouguoji.gjj.R
+import com.lukouguoji.gjj.databinding.DialogIntImpModifyStorageBinding
+import com.lukouguoji.module_base.base.BaseDialogModel
+import com.lukouguoji.module_base.http.net.NetApply
+import com.lukouguoji.module_base.ktx.launchCollect
+import com.lukouguoji.module_base.ktx.showToast
+import com.lukouguoji.module_base.ktx.verifyNullOrEmpty
+import dev.utils.app.info.KeyValue
+
+/**
+ * 国际进港 - 修改库位对话框
+ */
+class IntImpModifyStorageDialogModel(
+ private val callback: (IntImpModifyStorageDialogModel) -> Unit
+) : BaseDialogModel(DIALOG_TYPE_CENTER) {
+
+ // 库位列表
+ val locationList = MutableLiveData>()
+
+ // 选中的库位(存储的是code)
+ val selectedLocationCode = MutableLiveData("")
+
+ // 库位ID (后端需要的code)
+ var locationId: String = ""
+
+ // 库位名称 (后端需要的name)
+ var locationName: String = ""
+
+ override fun layoutId(): Int {
+ return R.layout.dialog_int_imp_modify_storage
+ }
+
+ override fun onDialogCreated(context: Context) {
+ binding.model = this
+ loadLocationList()
+
+ // 监听选择变化,更新locationId和locationName
+ selectedLocationCode.observeForever { code ->
+ val selectedItem = locationList.value?.find { it.value == code }
+ locationId = selectedItem?.value ?: ""
+ locationName = selectedItem?.key ?: ""
+ }
+ }
+
+ /**
+ * 加载库位列表
+ */
+ private fun loadLocationList() {
+ launchCollect({ NetApply.api.getLocationList(flag = 4) }) {
+ onSuccess = { result ->
+ val list = result.data?.map { it.toKeyValue() } ?: emptyList()
+ locationList.value = list
+ }
+ onFailed = { _, msg ->
+ showToast(msg ?: "加载库位列表失败")
+ }
+ }
+ }
+
+ /**
+ * 保存按钮点击
+ */
+ fun onSaveClick() {
+ if (selectedLocationCode.value.verifyNullOrEmpty("请选择库位")) {
+ return
+ }
+ dismiss()
+ callback(this)
+ }
+}
diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpMoveClearDialogModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpMoveClearDialogModel.kt
new file mode 100644
index 0000000..a5e5528
--- /dev/null
+++ b/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpMoveClearDialogModel.kt
@@ -0,0 +1,47 @@
+package com.lukouguoji.gjj.dialog
+
+import android.content.Context
+import androidx.lifecycle.MutableLiveData
+import com.lukouguoji.gjj.R
+import com.lukouguoji.gjj.databinding.DialogIntImpMoveClearBinding
+import com.lukouguoji.module_base.base.BaseDialogModel
+import com.lukouguoji.module_base.ktx.verifyNullOrEmpty
+import dev.utils.app.info.KeyValue
+
+/**
+ * 国际进港移库 - 清仓操作对话框
+ */
+class IntImpMoveClearDialogModel(
+ private val callback: (IntImpMoveClearDialogModel) -> 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_imp_move_clear
+ }
+
+ override fun onDialogCreated(context: Context) {
+ binding.model = this
+ }
+
+ /**
+ * 保存按钮点击
+ */
+ fun onSaveClick() {
+ if (clearNormal.value.verifyNullOrEmpty("请选择清仓正常")) {
+ return
+ }
+ dismiss()
+ callback(this)
+ }
+}
diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpPickUpRecordViewHolder.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpPickUpRecordViewHolder.kt
new file mode 100644
index 0000000..cbaa252
--- /dev/null
+++ b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpPickUpRecordViewHolder.kt
@@ -0,0 +1,32 @@
+package com.lukouguoji.gjj.holder
+
+import android.view.View
+import com.lukouguoji.gjj.activity.IntImpPickUpRecordDetailsActivity
+import com.lukouguoji.gjj.databinding.ItemIntImpPickUpRecordBinding
+import com.lukouguoji.module_base.base.BaseViewHolder
+import com.lukouguoji.module_base.bean.IntImpPickUpRecordBean
+
+/**
+ * 国际进港-提取记录 ViewHolder
+ */
+class IntImpPickUpRecordViewHolder(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()
+ }
+
+ // 列表项点击进入提取详情
+ itemView.setOnClickListener {
+ IntImpPickUpRecordDetailsActivity.start(itemView.context, bean.id)
+ }
+ }
+}
diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpStorageUseSubViewHolder.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpStorageUseSubViewHolder.kt
new file mode 100644
index 0000000..934ee41
--- /dev/null
+++ b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpStorageUseSubViewHolder.kt
@@ -0,0 +1,45 @@
+package com.lukouguoji.gjj.holder
+
+import android.view.View
+import androidx.recyclerview.widget.RecyclerView
+import com.lukouguoji.gjj.databinding.ItemIntImpStorageUseSubBinding
+import com.lukouguoji.module_base.base.BaseViewHolder
+import com.lukouguoji.module_base.bean.GjcMaWb
+import com.lukouguoji.module_base.bean.GjcStorageUse
+
+/**
+ * 国际进港-仓库 库位明细行 ViewHolder
+ */
+class IntImpStorageUseSubViewHolder(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.ivCheckbox.setOnClickListener {
+ // 切换子列表项的选择状态
+ val newCheckedState = !bean.checked.get()
+ bean.checked.set(newCheckedState)
+ binding.executePendingBindings()
+
+ // 反向联动主列表项(仅在勾选时联动)
+ updateParentCheckState(newCheckedState)
+ }
+ }
+
+ /**
+ * 更新父列表项的选择状态
+ */
+ private fun updateParentCheckState(newCheckedState: Boolean) {
+ val recyclerView = itemView.parent as? RecyclerView ?: return
+ val parentBean = recyclerView.tag as? GjcMaWb ?: return
+
+ if (newCheckedState) {
+ parentBean.checked.set(true)
+ }
+ }
+}
diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpStorageUseViewHolder.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpStorageUseViewHolder.kt
new file mode 100644
index 0000000..280cff1
--- /dev/null
+++ b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpStorageUseViewHolder.kt
@@ -0,0 +1,54 @@
+package com.lukouguoji.gjj.holder
+
+import android.view.View
+import com.lukouguoji.gjj.R
+import com.lukouguoji.gjj.databinding.ItemIntImpStorageUseBinding
+import com.lukouguoji.module_base.adapter.setCommonAdapter
+import com.lukouguoji.module_base.base.BaseViewHolder
+import com.lukouguoji.module_base.bean.GjcMaWb
+import com.lukouguoji.module_base.ktx.refresh
+
+/**
+ * 国际进港-仓库 ViewHolder
+ */
+class IntImpStorageUseViewHolder(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 {
+ val newCheckedState = !bean.checked.get()
+ bean.checked.set(newCheckedState)
+
+ // 联动勾选/取消所有子列表项
+ bean.storageUseList?.forEach { storageUse ->
+ storageUse.checked.set(newCheckedState)
+ }
+
+ binding.executePendingBindings()
+ binding.rvSub.adapter?.notifyDataSetChanged()
+ }
+
+ // 展开按钮点击事件
+ binding.ivShow.setOnClickListener {
+ bean.showMore.set(!bean.showMore.get())
+ }
+
+ // 初始化库位明细子列表 RecyclerView
+ setCommonAdapter(
+ binding.rvSub,
+ IntImpStorageUseSubViewHolder::class.java,
+ R.layout.item_int_imp_storage_use_sub
+ )
+
+ // 刷新库位明细数据(传递父Bean引用)
+ val storageUseList = bean.storageUseList ?: emptyList()
+ binding.rvSub.tag = bean
+ binding.rvSub.refresh(storageUseList)
+ }
+}
diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMsgParseViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMsgParseViewModel.kt
index 4707b8d..ad84834 100644
--- a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMsgParseViewModel.kt
+++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMsgParseViewModel.kt
@@ -7,12 +7,15 @@ import dev.utils.common.DateUtils
import com.lukouguoji.module_base.ktx.formatDate
import com.lukouguoji.gjj.holder.IntImpMsgParseViewHolder
import com.lukouguoji.module_base.base.BasePageViewModel
+import com.lukouguoji.module_base.bean.FlightBean
import com.lukouguoji.module_base.bean.MsgReceivePool
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.noNull
import com.lukouguoji.module_base.ktx.showToast
import com.lukouguoji.module_base.ktx.toRequestBody
import dev.utils.app.info.KeyValue
@@ -28,10 +31,14 @@ class IntImpMsgParseViewModel : BasePageViewModel() {
val flightNo = MutableLiveData("") // 航班号
val sendAddress = MutableLiveData("") // 发站(择始发站)
val sendAddressList = MutableLiveData>(emptyList())
- val receiveAddress = MutableLiveData("HFE") // 收报地址(目的站)
+ val receiveAddress = MutableLiveData("") // 收报地址(目的站,由航班查询返回)
val msgType = MutableLiveData("") // 报文类型
val msgTypeList = MutableLiveData>(emptyList())
+ // ========== 航班查询 ==========
+ private var fid: String = "" // 航班ID
+ private var lastQueriedFlight = "" // 避免重复查询
+
// ========== 统计信息 ==========
val totalCount = MutableLiveData("0") // 合计条数
@@ -39,6 +46,12 @@ class IntImpMsgParseViewModel : BasePageViewModel() {
val isAllChecked = MutableLiveData(false)
init {
+ // 初始化报文类型静态数据
+ msgTypeList.value = listOf(
+ KeyValue("FFM", "FFM"),
+ KeyValue("FWB/FHL", "FWB/FHL")
+ )
+
// 监听全选状态,自动更新所有列表项
isAllChecked.observeForever { checked ->
val list = pageModel.rv?.commonAdapter()?.items as? List ?: return@observeForever
@@ -47,6 +60,68 @@ class IntImpMsgParseViewModel : BasePageViewModel() {
}
}
+ // ========== 航班级联查询 ==========
+
+ fun onFlightDateInputComplete() {
+ lastQueriedFlight = ""
+ queryFlightIfReady()
+ }
+
+ fun onFlightNoInputComplete() {
+ queryFlightIfReady()
+ }
+
+ private fun queryFlightIfReady() {
+ val fdate = flightDate.value
+ val fno = flightNo.value
+ if (fdate.isNullOrEmpty() || fno.isNullOrEmpty()) return
+
+ val key = "$fdate-$fno"
+ if (key == lastQueriedFlight) return
+ lastQueriedFlight = key
+
+ launchCollect({
+ NetApply.api.getGjFlightBean(
+ mapOf(
+ "fdate" to fdate,
+ "fno" to fno,
+ "ieFlag" to "I",
+ ).toRequestBody()
+ )
+ }) {
+ onSuccess = {
+ if (it.verifySuccess() && it.data != null) {
+ val flight = it.data!!
+ fid = flight.fid.noNull()
+ receiveAddress.value = flight.fdest.noNull()
+
+ // 构建始发站下拉列表:fdep + jtz(经停港)
+ val list = mutableListOf(
+ KeyValue(flight.fdep.noNull(), flight.fdep.noNull()),
+ )
+ if (!flight.jtz.isNullOrEmpty()) {
+ list.add(KeyValue(flight.jtz.noNull(), flight.jtz.noNull()))
+ }
+ sendAddressList.value = list
+ sendAddress.value = flight.fdep.noNull()
+ } else {
+ fid = ""
+ receiveAddress.value = ""
+ sendAddressList.value = emptyList()
+ sendAddress.value = ""
+ showToast(it.msg.noNull("获取航班信息失败"))
+ }
+ }
+
+ onFailed = { _, _ ->
+ fid = ""
+ receiveAddress.value = ""
+ sendAddressList.value = listOf(KeyValue("全部", ""))
+ sendAddress.value = ""
+ }
+ }
+ }
+
// ========== 适配器配置 ==========
val itemViewHolder = IntImpMsgParseViewHolder::class.java
val itemLayoutId = R.layout.item_int_imp_msg_parse
@@ -55,6 +130,10 @@ class IntImpMsgParseViewModel : BasePageViewModel() {
* 搜索按钮点击
*/
fun searchClick() {
+ if (msgType.value.isNullOrEmpty()) {
+ showToast("请选择报文类型")
+ return
+ }
refresh()
}
@@ -103,13 +182,18 @@ class IntImpMsgParseViewModel : BasePageViewModel() {
* 获取数据(重写BasePageViewModel)
*/
override fun getData() {
- // 构建搜索条件
- val filterParams = mutableMapOf(
- "fdate" to flightDate.value?.ifEmpty { null },
- "fno" to flightNo.value?.ifEmpty { null },
+ // 构建搜索条件:优先用 fid,否则用 fdate + fno
+ val filterParams = mutableMapOf(
"sendAddress" to sendAddress.value?.ifEmpty { null },
+ "receiveAddress" to receiveAddress.value?.ifEmpty { null },
"msgType" to msgType.value?.ifEmpty { null }
)
+ if (fid.isNotEmpty()) {
+ filterParams["fid"] = fid
+ } else {
+ filterParams["fdate"] = flightDate.value?.ifEmpty { null }
+ filterParams["fno"] = flightNo.value?.ifEmpty { null }
+ }
// 列表参数(含分页)
val listParams = (filterParams + mapOf(
@@ -119,10 +203,9 @@ class IntImpMsgParseViewModel : BasePageViewModel() {
// 获取列表(带Loading)
launchLoadingCollect({ NetApply.api.getIntImpMsgList(listParams) }) {
- onSuccess = { result ->
- val pageInfo = result.data
- pageModel.handleListBean(pageInfo?.toBaseListBean())
- totalCount.value = (pageInfo?.total ?: 0).toString()
+ onSuccess = { pageInfo ->
+ pageModel.handleListBean(pageInfo.toBaseListBean())
+ totalCount.value = (pageInfo.total ?: 0).toString()
}
}
}
diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpPickUpRecordDetailsViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpPickUpRecordDetailsViewModel.kt
new file mode 100644
index 0000000..0ed31e4
--- /dev/null
+++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpPickUpRecordDetailsViewModel.kt
@@ -0,0 +1,42 @@
+package com.lukouguoji.gjj.viewModel
+
+import android.content.Intent
+import androidx.lifecycle.MutableLiveData
+import com.lukouguoji.module_base.base.BaseViewModel
+import com.lukouguoji.module_base.bean.IntImpPickUpRecordBean
+import com.lukouguoji.module_base.common.Constant
+import com.lukouguoji.module_base.http.net.NetApply
+import com.lukouguoji.module_base.ktx.launchLoadingCollect
+import com.lukouguoji.module_base.ktx.showToast
+import com.lukouguoji.module_base.ktx.toRequestBody
+
+/**
+ * 国际进港提取详情 ViewModel
+ */
+class IntImpPickUpRecordDetailsViewModel : BaseViewModel() {
+
+ var recordId: Long = 0
+
+ val dataBean = MutableLiveData(IntImpPickUpRecordBean())
+
+ fun initOnCreated(intent: Intent) {
+ recordId = intent.getLongExtra(Constant.Key.ID, 0)
+ if (recordId > 0) {
+ getData()
+ } else {
+ showToast("参数错误")
+ getTopActivity().finish()
+ }
+ }
+
+ private fun getData() {
+ val params = mapOf("id" to recordId).toRequestBody()
+ launchLoadingCollect({
+ NetApply.api.getIntImpPickUpRecordDetails(params)
+ }) {
+ onSuccess = {
+ dataBean.value = it.data ?: IntImpPickUpRecordBean()
+ }
+ }
+ }
+}
diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpPickUpRecordViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpPickUpRecordViewModel.kt
new file mode 100644
index 0000000..c491364
--- /dev/null
+++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpPickUpRecordViewModel.kt
@@ -0,0 +1,191 @@
+package com.lukouguoji.gjj.viewModel
+
+import android.app.Activity
+import android.content.Intent
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.viewModelScope
+import com.lukouguoji.gjj.R
+import com.lukouguoji.gjj.holder.IntImpPickUpRecordViewHolder
+import com.lukouguoji.module_base.base.BasePageViewModel
+import com.lukouguoji.module_base.bean.IntImpPickUpRecordBean
+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.noNull
+import com.lukouguoji.module_base.ktx.showToast
+import com.lukouguoji.module_base.ktx.toRequestBody
+import com.lukouguoji.module_base.model.ScanModel
+import com.lukouguoji.module_base.util.DictUtils
+import dev.utils.app.info.KeyValue
+import kotlinx.coroutines.launch
+
+/**
+ * 国际进港-提取记录 ViewModel
+ */
+class IntImpPickUpRecordViewModel : BasePageViewModel() {
+
+ // ========== 筛选条件 ==========
+ val paymentDateStart = MutableLiveData("") // 缴费日期起
+ val paymentDateEnd = MutableLiveData("") // 缴费日期止
+ val agentCode = MutableLiveData("") // 代理人
+ val spCode = MutableLiveData("") // 特码
+ val wbNo = MutableLiveData("") // 运单号
+
+ // ========== 下拉列表数据源 ==========
+ val agentList = MutableLiveData(listOf(KeyValue("全部", "")))
+ val spCodeList = MutableLiveData>(emptyList())
+
+ // ========== 统计信息 ==========
+ 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 = IntImpPickUpRecordViewHolder::class.java
+ val itemLayoutId = R.layout.item_int_imp_pick_up_record
+
+ /**
+ * 初始化代理人列表
+ */
+ fun initAgentList() {
+ launchCollect({ NetApply.api.getIntImpAgentList() }) {
+ onSuccess = { result ->
+ val list = mutableListOf(KeyValue("全部", ""))
+ result.data?.forEach {
+ list.add(KeyValue(it.name ?: "", it.code ?: ""))
+ }
+ agentList.value = list
+ }
+ }
+ }
+
+ /**
+ * 初始化特码列表
+ */
+ fun initSpecialCodeList() {
+ DictUtils.getSpecialCodeList(
+ flag = 1, // 国际
+ ieFlag = "I", // 进港
+ parentcode = ""
+ ) {
+ spCodeList.value = it
+ }
+ }
+
+ /**
+ * 搜索按钮点击
+ */
+ fun searchClick() {
+ refresh()
+ }
+
+ /**
+ * 扫码运单号
+ */
+ fun scanWbNo() {
+ ScanModel.startScan(getTopActivity(), Constant.RequestCode.WAYBILL)
+ }
+
+ /**
+ * 全选按钮点击
+ */
+ 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 clearPickUp(selectedItems: List) {
+ if (selectedItems.isEmpty()) {
+ showToast("请选择要清除提货的记录")
+ return
+ }
+
+ val params = selectedItems.toRequestBody()
+
+ launchLoadingCollect({ NetApply.api.clearIntImpPickUp(params) }) {
+ onSuccess = {
+ showToast("清除提货成功")
+ viewModelScope.launch {
+ FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh")
+ }
+ refresh()
+ }
+ onFailed = { _, msg ->
+ showToast(msg.noNull("清除提货失败"))
+ }
+ }
+ }
+
+ /**
+ * 获取列表数据
+ */
+ override fun getData() {
+ val filterParams = mapOf(
+ "paymentDateStart" to paymentDateStart.value?.ifEmpty { null },
+ "paymentDateEnd" to paymentDateEnd.value?.ifEmpty { null },
+ "agentCode" to agentCode.value?.ifEmpty { null },
+ "spCode" to spCode.value?.ifEmpty { null },
+ "wbNo" to wbNo.value?.ifEmpty { null }
+ )
+
+ val listParams = (filterParams + mapOf(
+ "pageNum" to pageModel.page,
+ "pageSize" to pageModel.limit
+ )).toRequestBody()
+
+ val totalParams = filterParams.toRequestBody()
+
+ launchLoadingCollect({ NetApply.api.getIntImpPickUpRecordList(listParams) }) {
+ onSuccess = { result ->
+ pageModel.handleDataList(result.list)
+ pageModel.haveMore.postValue((result.pages) > pageModel.page)
+ }
+ }
+
+ launchCollect({ NetApply.api.getIntImpPickUpRecordTotal(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()
+ }
+ }
+ }
+
+ /**
+ * 处理扫码结果
+ */
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ if (resultCode == Activity.RESULT_OK && data != null) {
+ when (requestCode) {
+ Constant.RequestCode.WAYBILL -> {
+ wbNo.value = data.getStringExtra(Constant.Result.CODED_CONTENT)
+ refresh()
+ }
+ }
+ }
+ }
+}
diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpStorageUseViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpStorageUseViewModel.kt
new file mode 100644
index 0000000..64719bc
--- /dev/null
+++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpStorageUseViewModel.kt
@@ -0,0 +1,287 @@
+package com.lukouguoji.gjj.viewModel
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.viewModelScope
+import com.lukouguoji.gjj.R
+import com.lukouguoji.gjj.holder.IntImpStorageUseViewHolder
+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
+
+/**
+ * 国际进港-仓库 ViewModel
+ */
+class IntImpStorageUseViewModel : BasePageViewModel() {
+
+ // ========== 筛选条件 ==========
+ val flightDate = MutableLiveData(Date().formatDate()) // 航班日期,默认今天
+ val flightNo = MutableLiveData("") // 航班号
+ val clearResult = MutableLiveData("") // 清仓综合结果
+ val clearResultList = MutableLiveData>() // 清仓综合结果列表
+ val wbNo = MutableLiveData("") // 运单号
+ val location = MutableLiveData("") // 库位号
+
+ // ========== 统计信息 ==========
+ val totalWbNumber = MutableLiveData("0") // 总票数
+ val totalPc = MutableLiveData("0") // 总件数
+ val totalWeight = MutableLiveData("0") // 总重量
+
+ // ========== 全选状态 ==========
+ val isAllChecked = MutableLiveData(false)
+
+ // ========== 全局展开状态 ==========
+ val isAllExpanded = MutableLiveData(false)
+
+ init {
+ clearResultList.value = listOf(
+ KeyValue("全部", ""),
+ KeyValue("正常", "0"),
+ KeyValue("异常", "1")
+ )
+
+ 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 = IntImpStorageUseViewHolder::class.java
+ val itemLayoutId = R.layout.item_int_imp_storage_use
+
+ fun searchClick() {
+ refresh()
+ }
+
+ /**
+ * 全选按钮点击(联动勾选所有子列表项)
+ */
+ fun checkAllClick() {
+ val list = pageModel.rv?.commonAdapter()?.items as? List ?: return
+
+ val shouldCheckAll = !isAllChecked.value!!
+
+ list.forEach { maWb ->
+ maWb.checked.set(shouldCheckAll)
+ maWb.storageUseList?.forEach { storageUse ->
+ storageUse.checked.set(shouldCheckAll)
+ }
+ }
+
+ isAllChecked.value = shouldCheckAll
+
+ pageModel.rv?.commonAdapter()?.notifyDataSetChanged()
+ }
+
+ /**
+ * 切换全局展开/收起状态
+ */
+ fun toggleAllExpand() {
+ val list = pageModel.rv?.commonAdapter()?.items as? List ?: return
+
+ val shouldExpand = !isAllExpanded.value!!
+ isAllExpanded.value = shouldExpand
+
+ list.forEach { bean ->
+ if (!bean.storageUseList.isNullOrEmpty()) {
+ bean.showMore.set(shouldExpand)
+ }
+ }
+
+ pageModel.rv?.commonAdapter()?.notifyDataSetChanged()
+ }
+
+ fun scanWbNo() {
+ ScanModel.startScan(getTopActivity(), Constant.RequestCode.WAYBILL)
+ }
+
+ fun clearStorage() {
+ // 由Activity显示对话框
+ }
+
+ /**
+ * 执行清仓操作
+ */
+ fun performClear(clearNormal: String, maWbListForClear: List) {
+ if (maWbListForClear.isEmpty()) {
+ showToast("请至少选择一个库位")
+ return
+ }
+
+ val params = mapOf(
+ "clearNormal" to clearNormal,
+ "maWbList" to maWbListForClear
+ ).toRequestBody()
+
+ launchLoadingCollect({ NetApply.api.clearIntImpStorage(params) }) {
+ onSuccess = {
+ showToast("清仓成功")
+ viewModelScope.launch {
+ FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh")
+ }
+ refresh()
+ }
+ onFailed = { _, msg ->
+ showToast(msg.noNull("清仓失败"))
+ }
+ }
+ }
+
+ fun modifyStorage() {
+ // 由Activity显示对话框
+ }
+
+ /**
+ * 执行修改库位操作
+ */
+ fun performModifyStorage(
+ locationName: String,
+ locationId: String,
+ storageUse: com.lukouguoji.module_base.bean.GjcStorageUse
+ ) {
+ if (locationName.isEmpty() || locationId.isEmpty()) {
+ showToast("请选择库位")
+ return
+ }
+
+ val updatedStorage = storageUse.copy(
+ location = locationName,
+ locationId = locationId.toLongOrNull() ?: 0
+ )
+
+ val params = updatedStorage.toRequestBody()
+
+ launchLoadingCollect({ NetApply.api.modifyIntImpStorage(params) }) {
+ onSuccess = {
+ showToast("修改库位成功")
+ viewModelScope.launch {
+ FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh")
+ }
+ refresh()
+ }
+ onFailed = { _, msg ->
+ showToast(msg.noNull("修改库位失败"))
+ }
+ }
+ }
+
+ fun outStorage() {
+ // 由Activity显示二次确认对话框
+ }
+
+ /**
+ * 执行出库操作
+ */
+ fun performOutStorage(selectedStorageList: List) {
+ if (selectedStorageList.isEmpty()) {
+ showToast("请选择要出库的库位")
+ return
+ }
+
+ val params = selectedStorageList.toRequestBody()
+
+ launchLoadingCollect({ NetApply.api.outIntImpStorage(params) }) {
+ onSuccess = {
+ showToast("出库成功")
+ viewModelScope.launch {
+ FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh")
+ }
+ refresh()
+ }
+ onFailed = { _, msg ->
+ showToast(msg.noNull("出库失败"))
+ }
+ }
+ }
+
+ fun inStorage() {
+ // 由Activity显示对话框
+ }
+
+ /**
+ * 执行入库操作
+ */
+ fun performInStorage(
+ locationName: String,
+ locationId: String,
+ maWbListForInStorage: List
+ ) {
+ if (maWbListForInStorage.isEmpty()) {
+ showToast("请至少选择一个单据")
+ return
+ }
+
+ if (locationName.isEmpty() || locationId.isEmpty()) {
+ showToast("请选择库位")
+ return
+ }
+
+ val params = mapOf(
+ "location" to locationName,
+ "locationId" to locationId.toLongOrNull(),
+ "maWbList" to maWbListForInStorage
+ ).toRequestBody()
+
+ launchLoadingCollect({ NetApply.api.inIntImpStorage(params) }) {
+ onSuccess = {
+ showToast("入库成功")
+ viewModelScope.launch {
+ FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh")
+ }
+ refresh()
+ }
+ onFailed = { _, msg ->
+ showToast(msg.noNull("入库失败"))
+ }
+ }
+ }
+
+ override fun getData() {
+ val filterParams = mapOf(
+ "fdate" to flightDate.value?.ifEmpty { null },
+ "fno" to flightNo.value?.ifEmpty { null },
+ "wbNo" to wbNo.value?.ifEmpty { null },
+ "location" to location.value?.ifEmpty { null }
+ )
+
+ val listParams = (filterParams + mapOf(
+ "pageNum" to pageModel.page,
+ "pageSize" to pageModel.limit
+ )).toRequestBody()
+
+ val totalParams = filterParams.toRequestBody()
+
+ launchLoadingCollect({ NetApply.api.getIntImpStorageUseList(listParams) }) {
+ onSuccess = { result ->
+ pageModel.handleDataList(result.list)
+ pageModel.haveMore.postValue((result.pages) > pageModel.page)
+ isAllExpanded.value = false
+ }
+ }
+
+ launchCollect({ NetApply.api.getIntImpStorageUseTotal(totalParams) }) {
+ onSuccess = { result ->
+ val data = result.data
+ totalWbNumber.value = (data?.wbNumber ?: 0).toString()
+ totalPc.value = (data?.totalPc ?: 0).toString()
+ totalWeight.value = (data?.totalWeight ?: 0.0).toString()
+ }
+ }
+ }
+}
diff --git a/module_gjj/src/main/res/layout/activity_int_imp_msg_parse.xml b/module_gjj/src/main/res/layout/activity_int_imp_msg_parse.xml
index e95e1a8..ddb0ad0 100644
--- a/module_gjj/src/main/res/layout/activity_int_imp_msg_parse.xml
+++ b/module_gjj/src/main/res/layout/activity_int_imp_msg_parse.xml
@@ -33,6 +33,7 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/module_gjj/src/main/res/layout/activity_int_imp_pick_up_record_details.xml b/module_gjj/src/main/res/layout/activity_int_imp_pick_up_record_details.xml
new file mode 100644
index 0000000..54ffcf5
--- /dev/null
+++ b/module_gjj/src/main/res/layout/activity_int_imp_pick_up_record_details.xml
@@ -0,0 +1,274 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/module_gjj/src/main/res/layout/activity_int_imp_storage_use.xml b/module_gjj/src/main/res/layout/activity_int_imp_storage_use.xml
new file mode 100644
index 0000000..92168b0
--- /dev/null
+++ b/module_gjj/src/main/res/layout/activity_int_imp_storage_use.xml
@@ -0,0 +1,252 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/module_gjj/src/main/res/layout/dialog_int_imp_in_storage.xml b/module_gjj/src/main/res/layout/dialog_int_imp_in_storage.xml
new file mode 100644
index 0000000..48c5bce
--- /dev/null
+++ b/module_gjj/src/main/res/layout/dialog_int_imp_in_storage.xml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/module_gjj/src/main/res/layout/dialog_int_imp_modify_storage.xml b/module_gjj/src/main/res/layout/dialog_int_imp_modify_storage.xml
new file mode 100644
index 0000000..f4fcb1f
--- /dev/null
+++ b/module_gjj/src/main/res/layout/dialog_int_imp_modify_storage.xml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/module_gjj/src/main/res/layout/dialog_int_imp_move_clear.xml b/module_gjj/src/main/res/layout/dialog_int_imp_move_clear.xml
new file mode 100644
index 0000000..6832dc3
--- /dev/null
+++ b/module_gjj/src/main/res/layout/dialog_int_imp_move_clear.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/module_gjj/src/main/res/layout/item_int_imp_pick_up_record.xml b/module_gjj/src/main/res/layout/item_int_imp_pick_up_record.xml
new file mode 100644
index 0000000..3018ec5
--- /dev/null
+++ b/module_gjj/src/main/res/layout/item_int_imp_pick_up_record.xml
@@ -0,0 +1,304 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/module_gjj/src/main/res/layout/item_int_imp_storage_use.xml b/module_gjj/src/main/res/layout/item_int_imp_storage_use.xml
new file mode 100644
index 0000000..3a221c7
--- /dev/null
+++ b/module_gjj/src/main/res/layout/item_int_imp_storage_use.xml
@@ -0,0 +1,411 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/module_gjj/src/main/res/layout/item_int_imp_storage_use_sub.xml b/module_gjj/src/main/res/layout/item_int_imp_storage_use_sub.xml
new file mode 100644
index 0000000..21e5f28
--- /dev/null
+++ b/module_gjj/src/main/res/layout/item_int_imp_storage_use_sub.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+