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/bean/GjcMaWb.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt index 0c55d98..b57eb8b 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt @@ -105,12 +105,17 @@ data class GjcMaWb( var activeId: Long? = null, // 有效值 // ==================== 关联列表(非数据库字段,用于展示) ==================== + @Transient var haWbList: List? = null, // 分单列表 + @Transient var storageUseList: List? = null, // 库位使用列表 + @Transient var attachList: List? = null // 附件列表 ) { // ==================== UI扩展字段 ==================== + @Transient val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态 + @Transient val showMore: ObservableBoolean = ObservableBoolean(false) // 展开状态 // 兼容现有API的isSelected属性 @@ -222,6 +227,7 @@ data class GjcHaWb( var activeId: Long? = null // 活动ID ) { // ==================== UI扩展字段 ==================== + @Transient val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态 // 兼容现有API的isSelected属性 diff --git a/module_base/src/main/res/mipmap-xhdpi/img_up.png b/module_base/src/main/res/mipmap-xhdpi/img_up.png new file mode 100644 index 0000000..56298cc Binary files /dev/null and b/module_base/src/main/res/mipmap-xhdpi/img_up.png differ diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryEditViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryEditViewModel.kt index 00e7049..b4fda7b 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryEditViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryEditViewModel.kt @@ -11,9 +11,11 @@ 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.launchLoadingCollect +import com.lukouguoji.module_base.ktx.launchCollect import com.lukouguoji.module_base.ktx.showToast import com.lukouguoji.module_base.ktx.toRequestBody import com.lukouguoji.module_base.ktx.verifyNullOrEmpty +import dev.utils.app.info.KeyValue import kotlinx.coroutines.launch /** @@ -24,6 +26,15 @@ class GjcQueryEditViewModel : BaseViewModel() { // 数据Bean val dataBean = MutableLiveData(GjcMaWb()) + // 运单ID(用于查询详情) + var maWbId: Long = 0 + + // 包装类型下拉列表 + val packageTypeList = MutableLiveData>(emptyList()) + + // 运单类型下拉列表 + val waybillTypeList = MutableLiveData>(emptyList()) + /** * 初始化数据 */ @@ -31,7 +42,17 @@ class GjcQueryEditViewModel : BaseViewModel() { val jsonData = intent.getStringExtra(Constant.Key.DATA) ?: "" if (jsonData.isNotEmpty()) { try { - dataBean.value = Gson().fromJson(jsonData, GjcMaWb::class.java) + val tempBean = Gson().fromJson(jsonData, GjcMaWb::class.java) + maWbId = tempBean.maWbId ?: 0 // 保存ID用于查询详情 + + // 加载包装类型下拉列表 + loadPackageTypeList() + + // 加载运单类型下拉列表 + loadWaybillTypeList() + + // 调用详情接口获取完整数据 + loadDetails() } catch (e: Exception) { showToast("数据解析失败") getTopActivity().finish() @@ -42,6 +63,165 @@ class GjcQueryEditViewModel : BaseViewModel() { } } + /** + * 加载包装类型下拉列表 + */ + private fun loadPackageTypeList() { + launchCollect({ NetApply.api.getPackTypeList() }) { + onSuccess = { result -> + // 转换为 KeyValue 列表,key 和 value 都使用 name(忽略 code) + val keyValueList = result.data?.mapNotNull { bean -> + bean.name?.let { name -> KeyValue(name, name) } + } ?: emptyList() + packageTypeList.value = keyValueList + } + } + } + + /** + * 加载运单类型下拉列表 + * 使用接口: POST /typeCode/awb?type=10 (10代表国际出港) + */ + private fun loadWaybillTypeList() { + launchCollect({ NetApply.api.getWaybillTypeList("10") }) { + onSuccess = { result -> + // 转换为 KeyValue 列表,key 使用 name(显示),value 使用 code(存储和提交) + val keyValueList = result.data?.mapNotNull { bean -> + if (bean.name != null && bean.code != null) { + KeyValue(bean.name, bean.code) + } else null + } ?: emptyList() + waybillTypeList.value = keyValueList + } + } + } + + /** + * 加载运单详情数据 + */ + private fun loadDetails() { + if (maWbId == 0L) { + showToast("运单ID不存在") + getTopActivity().finish() + return + } + + launchLoadingCollect({ NetApply.api.getGjcQueryDetails(maWbId) }) { + onSuccess = { result -> + val data = result.data ?: emptyMap() + + // 1. 提取 maWb 对象(主要数据) + val maWb = data["maWb"] as? Map ?: emptyMap() + + // 2. 提取 maWbM 对象(海关扩展数据) + val maWbM = data["maWbM"] as? Map ?: emptyMap() + + // 3. 提取 warehouseList(仓库列表,用于计算入库件数和入库重量) + val warehouseList = data["warehouseList"] as? List> ?: emptyList() + + // 4. 合并两个对象 + val mergedData = mutableMapOf() + mergedData.putAll(maWb) + mergedData.putAll(maWbM) + + // 5. 特殊字段处理 + // 5.1 运单号: 组合 prefix + no + val prefix = maWb["prefix"] as? String ?: "" + val no = maWb["no"] as? String ?: "" + if (prefix.isNotEmpty() && no.isNotEmpty()) { + mergedData["wbNo"] = "$prefix$no" + } + + // 5.2 代理人: 如果 agentName 为空,使用 agentCode + if (!mergedData.containsKey("agentName") || (mergedData["agentName"] as? String).isNullOrEmpty()) { + maWb["agentCode"]?.let { mergedData["agentName"] = it } + } + + // 5.3 入库件数和入库重量: 从 warehouseList 计算总和 + if (warehouseList.isNotEmpty()) { + var totalPc = 0L + var totalWeight = 0.0 + + warehouseList.forEach { warehouse -> + // 提取 pc(件数)并累加 + val pc = warehouse["pc"] + when (pc) { + is Number -> totalPc += pc.toLong() + is String -> totalPc += pc.toLongOrNull() ?: 0L + } + + // 提取 weight(重量)并累加 + val weight = warehouse["weight"] + when (weight) { + is Number -> totalWeight += weight.toDouble() + is String -> totalWeight += weight.toDoubleOrNull() ?: 0.0 + } + } + + // 覆盖原有的 arrivePc 和 arriveWeight + mergedData["arrivePc"] = totalPc + mergedData["arriveWeight"] = totalWeight + } + + // 6. 转换为 GjcMaWb 对象 + val bean = Gson().fromJson(Gson().toJson(mergedData), GjcMaWb::class.java) + + // 7. 匹配包装类型(支持 contains) + matchPackageType(bean) + + // 8. 匹配运单类型(支持 contains) + matchWaybillType(bean) + + dataBean.value = bean + } + } + } + + /** + * 匹配包装类型 + * 使用 contains 匹配,支持简写值和完整值 + */ + private fun matchPackageType(bean: GjcMaWb) { + val currentPackageType = bean.packageType + if (currentPackageType.isNullOrEmpty()) return + + val packageList = packageTypeList.value ?: emptyList() + if (packageList.isEmpty()) return + + // 使用 contains 匹配(完整值和简写值都支持) + val match = packageList.find { keyValue -> + keyValue.value?.contains(currentPackageType) == true + } + + if (match != null) { + // 使用匹配到的完整值 + bean.packageType = match.value + } + } + + /** + * 匹配运单类型 + * 使用 code 进行匹配(bean.awbType 存储的是 code) + * 显示时使用 name,但实际存储和提交的是 code + */ + private fun matchWaybillType(bean: GjcMaWb) { + val currentAwbTypeCode = bean.awbType + if (currentAwbTypeCode.isNullOrEmpty()) return + + val waybillList = waybillTypeList.value ?: emptyList() + if (waybillList.isEmpty()) return + + // 使用 code 进行精确匹配(value 字段存储的是 code) + val match = waybillList.find { keyValue -> + keyValue.value == currentAwbTypeCode + } + + if (match != null) { + // 使用匹配到的 code 值(确保存储的是 code,而不是 name) + bean.awbType = match.value + } + } + /** * 保存修改 */ @@ -53,7 +233,7 @@ class GjcQueryEditViewModel : BaseViewModel() { // 调用更新接口 launchLoadingCollect({ - NetApply.api.updateGjcMaWb(Gson().toJson(bean).toRequestBody()) + NetApply.api.updateGjcMaWb(bean.toRequestBody()) }) { onSuccess = { showToast("修改成功") diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryViewModel.kt index c45649d..e3afda6 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryViewModel.kt @@ -16,7 +16,7 @@ import com.lukouguoji.module_base.ktx.toRequestBody import com.lukouguoji.module_base.model.ScanModel import dev.utils.app.info.KeyValue import dev.utils.common.DateUtils -import com.lukouguoji.module_base.ktx.formatDate +import com.lukouguoji.module_base.ktx.formatDate /** * 国际出港查询ViewModel @@ -103,8 +103,8 @@ class GjcQueryViewModel : BasePageViewModel() { val listParams = mapOf( "pageNum" to pageModel.page, "pageSize" to pageModel.limit, - "fdateStart" to flightDateStart.value!!.ifEmpty { null }, - "fdateEnd" to flightDateEnd.value!!.ifEmpty { null }, + "beginDate" to flightDateStart.value!!.ifEmpty { null }, + "endDate" to flightDateEnd.value!!.ifEmpty { null }, "agentCode" to agentId.value!!.ifEmpty { null }, "outState" to outStatus.value!!.ifEmpty { null }, "wbNo" to waybillNo.value!!.ifEmpty { null }, diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt index 1ae415c..45eadc1 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt @@ -19,7 +19,7 @@ import com.lukouguoji.module_base.ktx.showToast import com.lukouguoji.module_base.ktx.toRequestBody import com.lukouguoji.module_base.model.ScanModel import dev.utils.common.DateUtils -import com.lukouguoji.module_base.ktx.formatDate +import com.lukouguoji.module_base.ktx.formatDate import kotlinx.coroutines.launch /** @@ -41,6 +41,14 @@ class IntExpArriveViewModel : BasePageViewModel() { // ========== 全选状态 ========== val isAllChecked = MutableLiveData(false) + // ========== 全局展开状态 ========== + /** + * 全局展开状态 + * - true: 全部展开 + * - false: 全部收起 + */ + val isAllExpanded = MutableLiveData(false) + init { // 监听全选状态,自动更新所有列表项 isAllChecked.observeForever { checked -> @@ -75,6 +83,28 @@ class IntExpArriveViewModel : BasePageViewModel() { pageModel.rv?.commonAdapter()?.notifyDataSetChanged() } + /** + * 切换全局展开/收起状态 + */ + fun toggleAllExpand() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + + // 切换全局状态 + val shouldExpand = !isAllExpanded.value!! + isAllExpanded.value = shouldExpand + + // 更新所有列表项的 showMore 状态 + list.forEach { bean -> + // 只有当有子列表时才设置展开状态 + if (!bean.haWbList.isNullOrEmpty()) { + bean.showMore.set(shouldExpand) + } + } + + // 刷新列表UI + pageModel.rv?.commonAdapter()?.notifyDataSetChanged() + } + /** * 扫码运单号 */ @@ -208,7 +238,11 @@ class IntExpArriveViewModel : BasePageViewModel() { // 获取列表 (带Loading) launchLoadingCollect({ NetApply.api.getIntExpArriveList(listParams) }) { - onSuccess = { pageModel.handleListBean(it) } + onSuccess = { + pageModel.handleListBean(it) + // 数据加载完成后,重置全局展开状态为收起 + isAllExpanded.value = false + } } // 获取统计信息 (后台请求) diff --git a/module_gjc/src/main/res/layout/activity_gjc_query_edit.xml b/module_gjc/src/main/res/layout/activity_gjc_query_edit.xml index c717c5f..1944873 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_query_edit.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_query_edit.xml @@ -90,7 +90,7 @@ title='@{"运单件数"}' titleLength="@{5}" type="@{DataLayoutType.INPUT}" - value='@{String.valueOf(viewModel.dataBean.pc)}' /> + value='@{viewModel.dataBean.pc != null ? String.valueOf(viewModel.dataBean.pc) : ``}' /> + value='@{viewModel.dataBean.weight != null ? String.valueOf(viewModel.dataBean.weight) : ``}' /> + value='@{viewModel.dataBean.arrivePc != null ? String.valueOf(viewModel.dataBean.arrivePc) : ``}' /> + value='@{viewModel.dataBean.arriveWeight != null ? String.valueOf(viewModel.dataBean.arriveWeight) : ``}' /> + value='@{viewModel.dataBean.weight != null ? String.valueOf(viewModel.dataBean.weight) : ``}' /> @@ -183,10 +183,11 @@ android:layout_height="wrap_content" android:layout_weight="1" enable="@{true}" - hint='@{"请输入包装类型"}' + hint='@{"请选择包装类型"}' + list="@{viewModel.packageTypeList}" title='@{"包装类型"}' titleLength="@{5}" - type="@{DataLayoutType.INPUT}" + type="@{DataLayoutType.SPINNER}" value='@={viewModel.dataBean.packageType}' /> @@ -241,27 +242,17 @@ android:layout_height="wrap_content" android:layout_weight="1" enable="@{true}" - hint='@{"请输入运单类型"}' + hint='@{"请选择运单类型"}' + list="@{viewModel.waybillTypeList}" title='@{"运单类型"}' titleLength="@{5}" - type="@{DataLayoutType.INPUT}" + type="@{DataLayoutType.SPINNER}" value='@={viewModel.dataBean.awbType}' /> - - + android:layout_weight="2" /> diff --git a/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml b/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml index 36887fe..2bd9d58 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml @@ -7,6 +7,8 @@ + + @@ -86,6 +88,17 @@ android:padding="2dp" android:src="@drawable/img_search" /> + + + diff --git a/module_gjc/src/main/res/layout/item_gjc_query.xml b/module_gjc/src/main/res/layout/item_gjc_query.xml index f1f83dd..387390e 100644 --- a/module_gjc/src/main/res/layout/item_gjc_query.xml +++ b/module_gjc/src/main/res/layout/item_gjc_query.xml @@ -93,13 +93,13 @@ + android:src="@mipmap/img_down" + visible="@{bean.haWbList != null && !bean.haWbList.empty}" />