From 7f00cbc44b3c214818fbc469c6133a8921b7fba7 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Sat, 27 Dec 2025 23:11:38 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9B=BD=E9=99=85=E8=BF=9B=E6=B8=AF-?= =?UTF-8?q?=E8=BF=9B=E6=B8=AF=E8=88=B1=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 7 + .../aerologic/ui/fragment/HomeFragment.kt | 12 + .../module_base/bean/GjjManifest.kt | 68 ++++ .../lukouguoji/module_base/common/Constant.kt | 1 + .../lukouguoji/module_base/http/net/Api.kt | 17 + .../module_base/router/ARouterConstants.kt | 1 + .../gjj/activity/IntImpManifestActivity.kt | 59 ++++ .../gjj/holder/IntImpManifestViewHolder.kt | 26 ++ .../gjj/viewModel/IntImpManifestViewModel.kt | 175 ++++++++++ .../res/layout/activity_int_imp_manifest.xml | 231 ++++++++++++ .../main/res/layout/item_int_imp_manifest.xml | 328 ++++++++++++++++++ 11 files changed, 925 insertions(+) create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/bean/GjjManifest.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpManifestActivity.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpManifestViewHolder.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpManifestViewModel.kt create mode 100644 module_gjj/src/main/res/layout/activity_int_imp_manifest.xml create mode 100644 module_gjj/src/main/res/layout/item_int_imp_manifest.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 786b9c0..f4cfb47 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -386,6 +386,13 @@ 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 f44dd5b..f3db299 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 @@ -437,6 +437,11 @@ class HomeFragment : Fragment() { ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_INT_ARR_AIR_MANIFEST) .navigation() } + // 进港舱单 + Constant.AuthName.IntImpManifest -> { + ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_INT_IMP_MANIFEST) + .navigation() + } /** * 航班查询 */ @@ -774,6 +779,13 @@ class HomeFragment : Fragment() { "原始舱单" ) ) + list.add( + RightMenu( + Constant.AuthName.IntImpManifest, + R.mipmap.img_bwjx, + "进港舱单" + ) + ) } Constant.AuthName.Flight -> { diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjjManifest.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjjManifest.kt new file mode 100644 index 0000000..e3aa982 --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjjManifest.kt @@ -0,0 +1,68 @@ +package com.lukouguoji.module_base.bean + +import androidx.databinding.ObservableBoolean + +/** + * 国际进港舱单Bean + * 用于国际进港舱单列表接口返回 + */ +data class GjjManifest( + var mfId: Long = 0, // 主键ID + var no: String = "", // 编号 + var prefix: String = "", // 前缀 + var wbNo: String = "", // 运单号 + var origin: String = "", // 货源地(始发站) + var dest: String = "", // 目的站 + var fdep: String = "", // 航班起始站 + var fdest: String = "", // 航班目的站 + var fid: Long = 0, // FID + var pc: Long = 0, // 件数 + var totalPc: Long = 0, // 总件数 + var weight: Double = 0.0, // 重量 + var volume: Double = 0.0, // 体积 + var goods: String = "", // 品名(英) + var goodsCn: String = "", // 品名(中) + var agentCode: String = "", // 代理代码 + var agentName: String = "", // 代理名称 + var awbType: String = "", // 运单类型 + var awbTypeName: String = "", // 运单类型(中) + var businessType: String = "", // 业务类型 + var cargoType: String = "", // 货物类型 + var spCode: String = "", // 特码 + var packageType: String = "", // 包装类型 + var haWbNum: Int = 0, // 分单数量 + var consignee: String = "", // 收货人 + var cashWeight: Double = 0.0, // 计费重量 + var cneeCode: String = "", // 收货人代码 + var cneeId: String = "", // 收货人ID + var cneeTel: String = "", // 收货人电话 + var edep: String = "", // 中转站1 + var edest1: String = "", // 中转站2 + var edest2: String = "", // 中转站3 + var efDate: String = "", // 中转航班日期 + var efNo: String = "", // 中转航班号 + var isEdiAwb: String = "", // 是否EDI运单 + var locFlag: String = "", // 库位标志 + var locFlagMft: String = "", // 舱单库位标志 + var location: String = "", // 库位 + var locationMft: String = "", // 舱单库位 + var opDate: String = "", // 操作日期 + var opId: String = "", // 操作人ID + var ref: String = "", // 参考 + var remark: String = "", // 备注 + var splitFlag: String = "", // 分批标志 + var subCode: String = "", // 子代码 + var unNumber: String = "", // 危险品编号 + var activeId: Long = 0 // 活动ID +) { + // 选中状态(用于多选功能) + val checked: ObservableBoolean = ObservableBoolean(false) + + // 兼容现有API的isSelected属性 + var isSelected: Boolean + get() = checked.get() + set(value) = checked.set(value) + + // 获取完整运单号 + fun getWaybillNo() = "$prefix$no" +} 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 424c631..1c218b5 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 @@ -267,6 +267,7 @@ interface Constant { const val GjjPacketParseActivity = "AppIntExpPacketParse" //报文解析(旧) const val IntImpMsgParseActivity = "AppIntImpMsgParse" //电报解析(电报生成) const val IntArrAirManifest = "AppIntArrAirManifest" //原始舱单 + const val IntImpManifest = "AppIntImpManifest" //进港舱单 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 90590c2..a5289f7 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 @@ -48,6 +48,7 @@ import com.lukouguoji.module_base.bean.GjjGoodsBean 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.GjjManifest import com.lukouguoji.module_base.bean.GjjManifestBean import com.lukouguoji.module_base.bean.GjjPackTypeBean import com.lukouguoji.module_base.bean.GjjTallyBean @@ -1569,4 +1570,20 @@ interface Api { */ @POST("IntImpAirManifest/deleteDeclare") suspend fun deleteIntArrManifestDeclare(@Body data: RequestBody): BaseResultBean + + /////////////////////////////////////////////////////////////////////////// + // 国际进港-进港舱单 + /////////////////////////////////////////////////////////////////////////// + + /** + * 国际进港舱单-分页查询 + */ + @POST("IntImpManifest/pageQuery") + suspend fun getIntImpManifestList(@Body data: RequestBody): BaseResultBean> + + /** + * 国际进港舱单-分页合计 + */ + @POST("IntImpManifest/pageQueryTotal") + suspend fun getIntImpManifestTotal(@Body data: RequestBody): BaseResultBean } \ No newline at end of file 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 93d370c..2e6ff6b 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 @@ -171,6 +171,7 @@ object ARouterConstants { const val ACTIVITY_URL_INT_ARR_AIR_MANIFEST = "/gjj/IntArrAirManifestActivity" //国际进港 原始舱单 const val ACTIVITY_URL_INT_ARR_AIR_MANIFEST_DETAILS = "/gjj/IntArrAirManifestDetailsActivity" //国际进港 原始舱单详情 const val ACTIVITY_URL_INT_ARR_SUPPLEMENT_INFO = "/gjj/IntArrSupplementInfoActivity" //国际进港 补充信息 + const val ACTIVITY_URL_INT_IMP_MANIFEST = "/gjj/IntImpManifestActivity" //国际进港 进港舱单 ///////////////// 航班查询模块 /** diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpManifestActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpManifestActivity.kt new file mode 100644 index 0000000..8a4ec87 --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpManifestActivity.kt @@ -0,0 +1,59 @@ +package com.lukouguoji.gjj.activity + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import com.alibaba.android.arouter.facade.annotation.Route +import com.lukouguoji.gjj.R +import com.lukouguoji.gjj.databinding.ActivityIntImpManifestBinding +import com.lukouguoji.gjj.viewModel.IntImpManifestViewModel +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_IMP_MANIFEST) +class IntImpManifestActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_imp_manifest + override fun viewModelClass() = IntImpManifestViewModel::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 (requestCode == Constant.RequestCode.WAYBILL && resultCode == Activity.RESULT_OK) { + viewModel.waybillNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT) + viewModel.searchClick() + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpManifestViewHolder.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpManifestViewHolder.kt new file mode 100644 index 0000000..a3b032a --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpManifestViewHolder.kt @@ -0,0 +1,26 @@ +package com.lukouguoji.gjj.holder + +import android.view.View +import com.lukouguoji.gjj.databinding.ItemIntImpManifestBinding +import com.lukouguoji.module_base.base.BaseViewHolder +import com.lukouguoji.module_base.bean.GjjManifest + +/** + * 国际进港舱单 ViewHolder + */ +class IntImpManifestViewHolder(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_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpManifestViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpManifestViewModel.kt new file mode 100644 index 0000000..85180e0 --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpManifestViewModel.kt @@ -0,0 +1,175 @@ +package com.lukouguoji.gjj.viewModel + +import android.app.Activity +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import com.lukouguoji.gjj.R +import com.lukouguoji.gjj.holder.IntImpManifestViewHolder +import com.lukouguoji.module_base.base.BasePageViewModel +import com.lukouguoji.module_base.bean.GjjManifest +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 IntImpManifestViewModel : BasePageViewModel() { + + // ========== 搜索条件 ========== + val flightDate = MutableLiveData("") // 航班日期 + val flightNo = MutableLiveData("") // 航班号 + val fdep = MutableLiveData("") // 始发站 + val waybillNo = 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 = IntImpManifestViewHolder::class.java + val itemLayoutId = R.layout.item_int_imp_manifest + + /** + * 搜索按钮点击 + */ + 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 onAddClick() { + showToast("新增功能开发中") + } + + /** + * 删除按钮点击 + */ + fun onDeleteClick() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + val selectedItems = list.filter { it.isSelected } + + if (selectedItems.isEmpty()) { + showToast("请选择要删除的记录") + return + } + + showToast("删除功能开发中") + } + + /** + * 分单管理(暂不实现) + */ + fun subManagementClick() { + showToast("分单管理功能开发中") + } + + /** + * 分拣理货(暂不实现) + */ + fun sortingTallyClick() { + showToast("分拣理货功能开发中") + } + + /** + * 货物发放(暂不实现) + */ + fun cargoReleaseClick() { + showToast("货物发放功能开发中") + } + + /** + * 获取数据(重写BasePageViewModel) + */ + override fun getData() { + // 构建搜索条件 + val filterParams = mapOf( + "fdate" to flightDate.value?.ifEmpty { null }, + "fno" to flightNo.value?.ifEmpty { null }, + "fdep" to fdep.value?.ifEmpty { null }, + "wbNo" to waybillNo.value?.ifEmpty { null } + ) + + // 列表参数(含分页) + val listParams = (filterParams + mapOf( + "pageNum" to pageModel.page, + "pageSize" to pageModel.limit + )).toRequestBody() + + // 统计参数(无分页) + val totalParams = filterParams.toRequestBody() + + // 获取列表(带Loading) + launchLoadingCollect({ NetApply.api.getIntImpManifestList(listParams) }) { + onSuccess = { result -> + // 处理PageInfo结构 + val pageInfo = result.data + if (pageInfo != null) { + val list = pageInfo.list ?: emptyList() + val pages = pageInfo.pages ?: 1 + + // 处理分页数据 + pageModel.handleDataList(list) + pageModel.haveMore.postValue(pages > pageModel.page) + } else { + pageModel.handleDataList(emptyList()) + pageModel.haveMore.postValue(false) + } + } + } + + // 获取统计信息(后台请求,不阻塞列表) + launchCollect({ NetApply.api.getIntImpManifestTotal(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_gjj/src/main/res/layout/activity_int_imp_manifest.xml b/module_gjj/src/main/res/layout/activity_int_imp_manifest.xml new file mode 100644 index 0000000..bcbded5 --- /dev/null +++ b/module_gjj/src/main/res/layout/activity_int_imp_manifest.xml @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/item_int_imp_manifest.xml b/module_gjj/src/main/res/layout/item_int_imp_manifest.xml new file mode 100644 index 0000000..9d97eb3 --- /dev/null +++ b/module_gjj/src/main/res/layout/item_int_imp_manifest.xml @@ -0,0 +1,328 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +