From a672e3927cf81f5ba2d7c5076b4d063add1af4a3 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 26 Dec 2025 23:20:38 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9B=BD=E9=99=85=E8=BF=9B=E6=B8=AF-?= =?UTF-8?q?=E5=8E=9F=E5=A7=8B=E8=88=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 3 +- app/src/main/AndroidManifest.xml | 21 ++ .../aerologic/ui/fragment/HomeFragment.kt | 12 + .../module_base/bean/GjjAirManifest.kt | 29 ++ .../module_base/bean/GjjDeclareParam.kt | 22 ++ .../module_base/bean/GjjImportManifest.kt | 126 +++++++ .../module_base/bean/GjjImportTally.kt | 75 ++++ .../lukouguoji/module_base/common/Constant.kt | 4 + .../lukouguoji/module_base/http/net/Api.kt | 35 ++ .../module_base/router/ARouterConstants.kt | 3 + .../gjj/activity/IntArrAirManifestActivity.kt | 67 ++++ .../IntArrAirManifestDetailsActivity.kt | 41 +++ .../activity/IntArrSupplementInfoActivity.kt | 41 +++ .../dialog/IntArrManifestDeleteDialogModel.kt | 58 +++ .../gjj/holder/IntArrAirManifestViewHolder.kt | 30 ++ .../IntArrAirManifestDetailsViewModel.kt | 26 ++ .../viewModel/IntArrAirManifestViewModel.kt | 311 +++++++++++++++++ .../IntArrSupplementInfoViewModel.kt | 44 +++ .../layout/activity_int_arr_air_manifest.xml | 208 +++++++++++ .../activity_int_arr_air_manifest_details.xml | 272 +++++++++++++++ .../activity_int_arr_supplement_info.xml | 309 ++++++++++++++++ .../layout/dialog_int_arr_manifest_delete.xml | 138 ++++++++ .../res/layout/item_int_arr_air_manifest.xml | 329 ++++++++++++++++++ 23 files changed, 2203 insertions(+), 1 deletion(-) create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/bean/GjjAirManifest.kt create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/bean/GjjDeclareParam.kt create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/bean/GjjImportManifest.kt create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/bean/GjjImportTally.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntArrAirManifestActivity.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntArrAirManifestDetailsActivity.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntArrSupplementInfoActivity.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntArrManifestDeleteDialogModel.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntArrAirManifestViewHolder.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntArrAirManifestDetailsViewModel.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntArrAirManifestViewModel.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntArrSupplementInfoViewModel.kt create mode 100644 module_gjj/src/main/res/layout/activity_int_arr_air_manifest.xml create mode 100644 module_gjj/src/main/res/layout/activity_int_arr_air_manifest_details.xml create mode 100644 module_gjj/src/main/res/layout/activity_int_arr_supplement_info.xml create mode 100644 module_gjj/src/main/res/layout/dialog_int_arr_manifest_delete.xml create mode 100644 module_gjj/src/main/res/layout/item_int_arr_air_manifest.xml diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 70d04fe..6e32389 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -37,7 +37,8 @@ "Bash(ls:*)", "Bash(xargs rm:*)", "Bash(git -C /Users/kid/Development/Fusion/Projects/aerologic-app stash)", - "WebFetch(domain:api.apifox.cn)" + "WebFetch(domain:api.apifox.cn)", + "Bash(sips:*)" ], "deny": [], "ask": [] diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8630dcc..786b9c0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -365,6 +365,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 91dfdd0..f44dd5b 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 @@ -432,6 +432,11 @@ class HomeFragment : Fragment() { ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_INT_IMP_MSG_PARSE) .navigation() } + // 原始舱单 + Constant.AuthName.IntArrAirManifest -> { + ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_INT_ARR_AIR_MANIFEST) + .navigation() + } /** * 航班查询 */ @@ -762,6 +767,13 @@ class HomeFragment : Fragment() { "电报解析" ) ) + list.add( + RightMenu( + Constant.AuthName.IntArrAirManifest, + R.mipmap.img_bwjx, + "原始舱单" + ) + ) } Constant.AuthName.Flight -> { diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjjAirManifest.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjjAirManifest.kt new file mode 100644 index 0000000..8d3f6bb --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjjAirManifest.kt @@ -0,0 +1,29 @@ +package com.lukouguoji.module_base.bean + +import androidx.databinding.ObservableBoolean + +/** + * 国际进港航空舱单(包含主单和分单) + */ +data class GjjAirManifest( + // 主单原始舱单 + var maWbList: GjjImportManifest? = null, + // 分单原始舱单列表 + var haWbList: List? = null +) { + // ========== UI扩展字段 ========== + // 选中状态(用于列表多选) + val checked: ObservableBoolean = ObservableBoolean(false) + + // 兼容现有API的isSelected属性 + var isSelected: Boolean + get() = checked.get() + set(value) = checked.set(value) + + /** + * 获取主单用于显示 + */ + fun getMainManifest(): GjjImportManifest { + return maWbList ?: GjjImportManifest() + } +} diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjjDeclareParam.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjjDeclareParam.kt new file mode 100644 index 0000000..5795791 --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjjDeclareParam.kt @@ -0,0 +1,22 @@ +package com.lukouguoji.module_base.bean + +/** + * 国际进港舱单/理货申报参数 + */ +data class GjjDeclareParam( + var dcode: String = "", + var dcontactsName: String = "", + var dcontactsTel: String = "", + // 原始舱单主单列表 + var maWbList: List? = null, + // 原始舱单分单列表 + var haWbList: List? = null, + // 主单理货列表 + var mtallyList: List? = null, + // 分单理货列表 + var htallyList: List? = null, + // 重置状态原因 + var resetReason: String = "", + // 重置的状态(正常-'01';未申报-null-不传值) + var restStatus: String? = null +) diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjjImportManifest.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjjImportManifest.kt new file mode 100644 index 0000000..54a2fdc --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjjImportManifest.kt @@ -0,0 +1,126 @@ +package com.lukouguoji.module_base.bean + +import androidx.databinding.ObservableBoolean +import java.io.Serializable + +/** + * 国际进港原始舱单 + */ +data class GjjImportManifest( + // 代理代码 + var agentCode: String = "", + // 代理人名称(中) + var agentName: String = "", + // 运单类型 + var awbType: String = "", + // 运单类型(中) + var awbTypeName: String = "", + // 收货人 + var consignee: String = "", + // 收货人地址 + var consigneeAddress: String = "", + // 收货人公司代码 + var consigneeCode: String = "", + // 收货人通讯方式 + var consigneeComType: String = "", + // 收货人国家代码 + var consigneeCountryCode: String = "", + // 收货人名称 + var consigneeName: String = "", + // 收货人电话号码 + var consigneePNum: String = "", + // 发货人地址 + var consignorAddress: String = "", + // 发货人公司代码 + var consignorCode: String = "", + // 发货人通讯方式 + var consignorComType: String = "", + // 发货人国家代码 + var consignorCountryCode: String = "", + // 发货人名称 + var consignorName: String = "", + // 发货人电话号码 + var consignorPNum: String = "", + // 目的地 + var dest: String = "", + // 危险品收货人通讯方式 + var dgrContactMame: String = "", + // 危险品收货人通讯方式 + var dgrContactNumber: String = "", + // 航班起始站 + var fdep: String = "", + // 航班目的站 + var fdest: String = "", + // 航班id + var fid: Long = 0, + // 运费支付方式 + var freightPayment: String = "", + // 品名 + var goods: String = "", + // 品名(中) + var goodsCn: String = "", + // 分单数量 + var haWbNum: Int = 0, + // 分单总件数 + var haWbTotalPc: Long = 0, + // 分单总重 + var haWbTotalWeight: Double = 0.0, + // 分单号 + var hno: String = "", + // 舱单申报删除次数 + var mftDCount: Long = 0, + // 舱单申报删除税率 + var mftDRate: Double = 0.0, + // 舱单报文编号 + var mftMsgId: String = "", + // 舱单申报次数 + var mftSCount: Long = 0, + // 舱单申报税率 + var mftSRate: Double = 0.0, + // 舱单申报状态 + var mftStatus: String = "", + // 编号 + var no: String = "", + // 货源地 + var origin: String = "", + // 件数 + var pc: Long = 0, + // 前缀 + var prefix: String = "", + // 备注 + var remark: String = "", + // 舱单报文回执 + var response: String = "", + // 发货人 + var shipper: String = "", + // 特码 + var spCode: String = "", + // 特货收货人通讯方式 + var speConsigneeComType: String = "", + // 特货收货人名称 + var speConsigneeName: String = "", + // 特货收货人联系号码 + var speConsigneePNum: String = "", + // 分批标志 + var splitFlag: String = "", + // 总件数 + var totalPc: Long = 0, + // 危险品编号 + var unNumber: String = "", + // 体积 + var volume: Double = 0.0, + // 主运单号(prefix+no拼接) + var wbNo: String = "", + // 重量 + var weight: Double = 0.0 +) : Serializable { + // ========== UI扩展字段 ========== + // 选中状态 + @Transient + 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/bean/GjjImportTally.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjjImportTally.kt new file mode 100644 index 0000000..65f1589 --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjjImportTally.kt @@ -0,0 +1,75 @@ +package com.lukouguoji.module_base.bean + +/** + * 国际进港理货数据 + */ +data class GjjImportTally( + // 有效ID + var activeId: Long = 0, + // 代理代码 + var agentCode: String = "", + // 代理(中文) + var agentName: String = "", + // 运单类型(5位代码) + var awbType: String = "", + // 运单类型(中文) + var awbTypeName: String = "", + // 提单号 + var billsNo: String = "", + // 车牌号 + var carNumber: String = "", + // 海关库区(2位代码) + var customsLib: String = "", + // 目的地(3位代码) + var dest: String = "", + // 航班日期 + var fdate: String = "", + // 航班目的地(3位代码) + var fdest: String = "", + // 航班号 + var fno: String = "", + // 货物描述 + var goods: String = "", + // 分单数量 + var haWbNum: Int = 0, + // 运单号 + var hno: String = "", + // 理货申报上一次消息ID + var lastMsgId: String = "", + // 理货申报上一次状态 + var lastStatus: String = "", + // 理货申报消息ID + var msgId: String = "", + // 编号(8位字符) + var no: String = "", + // 操作时间 + var opDate: String = "", + // 操作人ID + var opId: String = "", + // 始发地(3位代码) + var origin: String = "", + // 包装类型(2位代码) + var packageType: String = "", + // 件数 + var pc: Long = 0, + // 前缀(3位字符) + var prefix: String = "", + // 响应信息 + var response: String = "", + // 特货代码 + var spCode: String = "", + // 理货申报状态 + var status: String = "", + // 理货删除次数 + var tallyDCount: Long = 0, + // 理货删除费率 + var tallyDRate: Double = 0.0, + // 理货申报次数 + var tallySCount: Long = 0, + // 理货申报费率 + var tallySRate: Double = 0.0, + // 体积(m³) + var volume: Double = 0.0, + // 重量(kg) + var weight: Double = 0.0 +) 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 15a9955..424c631 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 @@ -133,6 +133,9 @@ interface Constant { // 运单 const val WAYBILL = 10002 + // 分单号 + const val HNO = 10006 + // 单号 const val CODE = 10003 const val ORDER = 10004 @@ -263,6 +266,7 @@ interface Constant { const val GjjPacketParseActivity = "AppIntExpPacketParse" //报文解析(旧) const val IntImpMsgParseActivity = "AppIntImpMsgParse" //电报解析(电报生成) + const val IntArrAirManifest = "AppIntArrAirManifest" //原始舱单 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 7468331..90590c2 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 @@ -43,6 +43,7 @@ import com.lukouguoji.module_base.bean.GjcWaybillDataBean import com.lukouguoji.module_base.bean.GjcWeighingBean import com.lukouguoji.module_base.bean.GjcWeighingRecordBean import com.lukouguoji.module_base.bean.GjcWeighingStatisticsBean +import com.lukouguoji.module_base.bean.GjjAirManifest import com.lukouguoji.module_base.bean.GjjGoodsBean import com.lukouguoji.module_base.bean.GjjGoodsDetailsBean import com.lukouguoji.module_base.bean.GjjGoodsTypeBean @@ -1534,4 +1535,38 @@ interface Api { */ @POST("IntImpMsg/batchGenerate") suspend fun batchGenerateMsg(@Body data: RequestBody): BaseResultBean + + /////////////////////////////////////////////////////////////////////////// + // 国际进港-原始舱单 + /////////////////////////////////////////////////////////////////////////// + + /** + * 国际进港原始舱单-分页查询 + */ + @POST("IntImpAirManifest/pageQuery") + suspend fun getIntArrAirManifestList(@Body data: RequestBody): BaseResultBean> + + /** + * 国际进港原始舱单-分页合计 + */ + @POST("IntImpAirManifest/pageQueryTotal") + suspend fun getIntArrAirManifestTotal(@Body data: RequestBody): BaseResultBean + + /** + * 国际进港原始舱单-舱单申报(分单+主单) + */ + @POST("IntImpAirManifest/declare") + suspend fun declareIntArrManifest(@Body data: RequestBody): BaseResultBean + + /** + * 国际进港原始舱单-重置舱单申报状态 + */ + @POST("IntImpAirManifest/resetDeclare") + suspend fun resetIntArrManifestStatus(@Body data: RequestBody): BaseResultBean + + /** + * 国际进港原始舱单-删除舱单申报 + */ + @POST("IntImpAirManifest/deleteDeclare") + suspend fun deleteIntArrManifestDeclare(@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 bacd947..93d370c 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 @@ -168,6 +168,9 @@ object ARouterConstants { const val ACTIVITY_URL_GJJ_GOODS = "/gjj/GjjGoodsListActivity" //国际进港 货物交接 const val ACTIVITY_URL_INT_IMP_MSG_PARSE = "/gjj/IntImpMsgParseActivity" //国际进港 电报解析(电报生成) const val ACTIVITY_URL_INT_ARR_TELEGRAM_DETAILS = "/gjj/IntArrTelegramDetailsActivity" //国际进港 电报详情 + 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" //国际进港 补充信息 ///////////////// 航班查询模块 /** diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntArrAirManifestActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntArrAirManifestActivity.kt new file mode 100644 index 0000000..3e68903 --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntArrAirManifestActivity.kt @@ -0,0 +1,67 @@ +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.ActivityIntArrAirManifestBinding +import com.lukouguoji.gjj.viewModel.IntArrAirManifestViewModel +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_ARR_AIR_MANIFEST) +class IntArrAirManifestActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_arr_air_manifest + override fun viewModelClass() = IntArrAirManifestViewModel::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) { + when (requestCode) { + Constant.RequestCode.WAYBILL -> { + viewModel.waybillNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT) + viewModel.searchClick() + } + Constant.RequestCode.HNO -> { + viewModel.houseNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT) + viewModel.searchClick() + } + } + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntArrAirManifestDetailsActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntArrAirManifestDetailsActivity.kt new file mode 100644 index 0000000..b19a62d --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntArrAirManifestDetailsActivity.kt @@ -0,0 +1,41 @@ +package com.lukouguoji.gjj.activity + +import android.content.Context +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.ActivityIntArrAirManifestDetailsBinding +import com.lukouguoji.gjj.viewModel.IntArrAirManifestDetailsViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.GjjImportManifest +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.router.ARouterConstants + +/** + * 国际进港原始舱单详情 + */ +@Route(path = ARouterConstants.ACTIVITY_URL_INT_ARR_AIR_MANIFEST_DETAILS) +class IntArrAirManifestDetailsActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_arr_air_manifest_details + override fun viewModelClass() = IntArrAirManifestDetailsViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("原始舱单详情") + binding.viewModel = viewModel + + // 初始化数据 + viewModel.initOnCreated(intent) + } + + companion object { + @JvmStatic + fun start(context: Context, manifest: GjjImportManifest) { + val starter = Intent(context, IntArrAirManifestDetailsActivity::class.java) + .putExtra(Constant.Key.DATA, manifest) + context.startActivity(starter) + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntArrSupplementInfoActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntArrSupplementInfoActivity.kt new file mode 100644 index 0000000..df4f2c1 --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntArrSupplementInfoActivity.kt @@ -0,0 +1,41 @@ +package com.lukouguoji.gjj.activity + +import android.content.Context +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.ActivityIntArrSupplementInfoBinding +import com.lukouguoji.gjj.viewModel.IntArrSupplementInfoViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.GjjImportManifest +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.router.ARouterConstants + +/** + * 国际进港补充信息(收发货人信息) + */ +@Route(path = ARouterConstants.ACTIVITY_URL_INT_ARR_SUPPLEMENT_INFO) +class IntArrSupplementInfoActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_arr_supplement_info + override fun viewModelClass() = IntArrSupplementInfoViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("收发货人信息") + binding.viewModel = viewModel + + // 初始化数据 + viewModel.initOnCreated(intent) + } + + companion object { + @JvmStatic + fun start(context: Context, manifest: GjjImportManifest) { + val starter = Intent(context, IntArrSupplementInfoActivity::class.java) + .putExtra(Constant.Key.DATA, manifest) + context.startActivity(starter) + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntArrManifestDeleteDialogModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntArrManifestDeleteDialogModel.kt new file mode 100644 index 0000000..2fb7358 --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntArrManifestDeleteDialogModel.kt @@ -0,0 +1,58 @@ +package com.lukouguoji.gjj.dialog + +import android.content.Context +import androidx.lifecycle.MutableLiveData +import com.lukouguoji.gjj.R +import com.lukouguoji.gjj.databinding.DialogIntArrManifestDeleteBinding +import com.lukouguoji.module_base.base.BaseDialogModel +import com.lukouguoji.module_base.ktx.verifyNullOrEmpty +import dev.utils.app.info.KeyValue + +/** + * 国际进港原始舱单 - 删除申报对话框 + */ +class IntArrManifestDeleteDialogModel( + val deleteReasonList: List, // 删除原因列表 + private val callback: (IntArrManifestDeleteDialogModel) -> Unit +) : BaseDialogModel(DIALOG_TYPE_CENTER) { + + // 删除原因代码(存储的是 code) + val deleteReason = MutableLiveData("") + + // 联系人姓名 + val contactName = MutableLiveData("") + + // 联系人电话 + val contactPhone = MutableLiveData("") + + override fun layoutId(): Int { + return R.layout.dialog_int_arr_manifest_delete + } + + override fun onDialogCreated(context: Context) { + binding.model = this + } + + /** + * 确认按钮点击 + */ + fun onConfirmClick() { + // 验证删除原因 + if (deleteReason.value.verifyNullOrEmpty("请选择删除原因")) { + return + } + + // 验证联系人姓名 + if (contactName.value.verifyNullOrEmpty("请输入联系人姓名")) { + return + } + + // 验证联系人电话 + if (contactPhone.value.verifyNullOrEmpty("请输入联系人电话")) { + return + } + + dismiss() + callback(this) + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntArrAirManifestViewHolder.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntArrAirManifestViewHolder.kt new file mode 100644 index 0000000..3c87601 --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntArrAirManifestViewHolder.kt @@ -0,0 +1,30 @@ +package com.lukouguoji.gjj.holder + +import android.view.View +import com.lukouguoji.gjj.R +import com.lukouguoji.gjj.databinding.ItemIntArrAirManifestBinding +import com.lukouguoji.module_base.base.BaseViewHolder +import com.lukouguoji.module_base.bean.GjjAirManifest + +/** + * 国际进港原始舱单 ViewHolder + */ +class IntArrAirManifestViewHolder(view: View) : + BaseViewHolder(view) { + + override fun onBind(item: Any?, position: Int) { + val bean = getItemBean(item) ?: return + val manifest = bean.getMainManifest() + + binding.bean = bean + binding.manifest = manifest + 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/IntArrAirManifestDetailsViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntArrAirManifestDetailsViewModel.kt new file mode 100644 index 0000000..8f5d99e --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntArrAirManifestDetailsViewModel.kt @@ -0,0 +1,26 @@ +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.GjjImportManifest +import com.lukouguoji.module_base.common.Constant + +/** + * 国际进港原始舱单详情 ViewModel + */ +class IntArrAirManifestDetailsViewModel : BaseViewModel() { + + // 舱单数据 + val dataBean = MutableLiveData() + + /** + * 初始化数据 + */ + fun initOnCreated(intent: Intent) { + val manifest = intent.getSerializableExtra(Constant.Key.DATA) as? GjjImportManifest + if (manifest != null) { + dataBean.value = manifest + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntArrAirManifestViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntArrAirManifestViewModel.kt new file mode 100644 index 0000000..29f89dd --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntArrAirManifestViewModel.kt @@ -0,0 +1,311 @@ +package com.lukouguoji.gjj.viewModel + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import com.lukouguoji.gjj.R +import com.lukouguoji.gjj.holder.IntArrAirManifestViewHolder +import com.lukouguoji.module_base.base.BasePageViewModel +import com.lukouguoji.module_base.bean.GjjAirManifest +import com.lukouguoji.module_base.bean.GjjDeclareParam +import com.lukouguoji.module_base.bean.GjjImportManifest +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 IntArrAirManifestViewModel : BasePageViewModel() { + + // ========== 搜索条件 ========== + val flightDate = MutableLiveData("") + val flightNo = MutableLiveData("") + val waybillNo = MutableLiveData("") + val houseNo = 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 = IntArrAirManifestViewHolder::class.java + val itemLayoutId = R.layout.item_int_arr_air_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 scanHouseNo() { + ScanModel.startScan(getTopActivity(), Constant.RequestCode.HNO) + } + + /** + * 状态重置按钮点击 + */ + fun resetStatusClick() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + val selectedItems = list.filter { it.isSelected } + + if (selectedItems.isEmpty()) { + showToast("请选择要重置的舱单") + return + } + + // 提取主单和分单 + val maWbList = mutableListOf() + val haWbList = mutableListOf() + + selectedItems.forEach { airManifest -> + airManifest.maWbList?.let { maWbList.add(it) } + airManifest.haWbList?.let { haWbList.addAll(it) } + } + + val param = GjjDeclareParam( + maWbList = maWbList, + haWbList = haWbList, + restStatus = null, // 未申报状态 + resetReason = "状态重置" + ) + + launchLoadingCollect({ NetApply.api.resetIntArrManifestStatus(param.toRequestBody()) }) { + onSuccess = { + showToast("状态重置成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + refresh() + } + } + } + + /** + * 补充信息按钮点击 + */ + fun supplementInfoClick() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + val selectedItems = list.filter { it.isSelected } + + if (selectedItems.isEmpty()) { + showToast("请选择要补充信息的舱单") + return + } + + // 获取第一个选中项的主单数据 + val manifest = selectedItems.firstOrNull()?.maWbList ?: return + + // 跳转到补充信息页面 + com.lukouguoji.gjj.activity.IntArrSupplementInfoActivity.start( + getTopActivity(), + manifest + ) + } + + /** + * 删除申报按钮点击 + */ + fun deleteDeclarationClick() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + val selectedItems = list.filter { it.isSelected } + + if (selectedItems.isEmpty()) { + showToast("请选择要删除申报的舱单") + return + } + + // 从接口获取删除原因列表 + launchLoadingCollect({ NetApply.api.getDelReasonList() }) { + onSuccess = { result -> + val deleteReasonList = result.data?.map { it.toKeyValue() } ?: emptyList() + + // 创建并显示弹框 + val dialog = com.lukouguoji.gjj.dialog.IntArrManifestDeleteDialogModel(deleteReasonList) { dialogModel -> + // 弹框确认后的回调 + // 提取主单和分单 + val maWbList = mutableListOf() + val haWbList = mutableListOf() + + selectedItems.forEach { airManifest -> + airManifest.maWbList?.let { maWbList.add(it) } + airManifest.haWbList?.let { haWbList.addAll(it) } + } + + val param = GjjDeclareParam( + dcode = dialogModel.deleteReason.value ?: "", + dcontactsName = dialogModel.contactName.value ?: "", + dcontactsTel = dialogModel.contactPhone.value ?: "", + maWbList = maWbList, + haWbList = haWbList + ) + + val requestData = param.toRequestBody() + + // 调用删除接口 + launchLoadingCollect({ NetApply.api.deleteIntArrManifestDeclare(requestData) }) { + onSuccess = { + showToast("删除申报成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + refresh() + } + } + } + + dialog.show() + } + } + } + + /** + * 舱单申报按钮点击 + */ + fun declareClick() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + val selectedItems = list.filter { it.isSelected } + + if (selectedItems.isEmpty()) { + showToast("请选择要申报的舱单") + return + } + + // 提取主单和分单 + val maWbList = mutableListOf() + val haWbList = mutableListOf() + + selectedItems.forEach { airManifest -> + airManifest.maWbList?.let { maWbList.add(it) } + airManifest.haWbList?.let { haWbList.addAll(it) } + } + + val param = GjjDeclareParam( + maWbList = maWbList, + haWbList = haWbList + ) + + launchLoadingCollect({ NetApply.api.declareIntArrManifest(param.toRequestBody()) }) { + 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 }, + "wbNo" to waybillNo.value?.ifEmpty { null }, + "hno" to houseNo.value?.ifEmpty { null } + ) + + // 列表参数(含分页) + val listParams = (filterParams + mapOf( + "pageNum" to pageModel.page, + "pageSize" to pageModel.limit + )).toRequestBody() + + // 统计参数(无分页) + val totalParams = filterParams.toRequestBody() + + // 获取列表(带Loading) + launchLoadingCollect({ NetApply.api.getIntArrAirManifestList(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.getIntArrAirManifestTotal(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 onItemClick(position: Int, type: Int) { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + val airManifest = list.getOrNull(position) ?: return + + // 获取主单数据 + val manifest = airManifest.maWbList ?: return + + // 跳转到详情页 + com.lukouguoji.gjj.activity.IntArrAirManifestDetailsActivity.start( + getTopActivity(), + manifest + ) + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntArrSupplementInfoViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntArrSupplementInfoViewModel.kt new file mode 100644 index 0000000..d983ac1 --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntArrSupplementInfoViewModel.kt @@ -0,0 +1,44 @@ +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.GjjImportManifest +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.ktx.showToast + +/** + * 国际进港补充信息 ViewModel + */ +class IntArrSupplementInfoViewModel : BaseViewModel() { + + // 数据对象 + val dataBean = MutableLiveData() + + /** + * 初始化数据 + */ + fun initOnCreated(intent: Intent) { + val manifest = intent.getSerializableExtra(Constant.Key.DATA) as? GjjImportManifest + if (manifest != null) { + dataBean.value = manifest + } else { + dataBean.value = GjjImportManifest() + } + } + + /** + * 取消按钮点击 - 暂不实现 + */ + fun cancel() { + showToast("取消功能暂未实现") + getTopActivity().finish() + } + + /** + * 保存按钮点击 - 暂不实现 + */ + fun save() { + showToast("保存功能暂未实现") + } +} diff --git a/module_gjj/src/main/res/layout/activity_int_arr_air_manifest.xml b/module_gjj/src/main/res/layout/activity_int_arr_air_manifest.xml new file mode 100644 index 0000000..f0d41f8 --- /dev/null +++ b/module_gjj/src/main/res/layout/activity_int_arr_air_manifest.xml @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/activity_int_arr_air_manifest_details.xml b/module_gjj/src/main/res/layout/activity_int_arr_air_manifest_details.xml new file mode 100644 index 0000000..9b6c3c9 --- /dev/null +++ b/module_gjj/src/main/res/layout/activity_int_arr_air_manifest_details.xml @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/activity_int_arr_supplement_info.xml b/module_gjj/src/main/res/layout/activity_int_arr_supplement_info.xml new file mode 100644 index 0000000..613ea44 --- /dev/null +++ b/module_gjj/src/main/res/layout/activity_int_arr_supplement_info.xml @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/dialog_int_arr_manifest_delete.xml b/module_gjj/src/main/res/layout/dialog_int_arr_manifest_delete.xml new file mode 100644 index 0000000..4d58efe --- /dev/null +++ b/module_gjj/src/main/res/layout/dialog_int_arr_manifest_delete.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/item_int_arr_air_manifest.xml b/module_gjj/src/main/res/layout/item_int_arr_air_manifest.xml new file mode 100644 index 0000000..113309a --- /dev/null +++ b/module_gjj/src/main/res/layout/item_int_arr_air_manifest.xml @@ -0,0 +1,329 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +