feat: opt 出港查询-修改
This commit is contained in:
@@ -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(),
|
||||
|
||||
@@ -105,12 +105,17 @@ data class GjcMaWb(
|
||||
var activeId: Long? = null, // 有效值
|
||||
|
||||
// ==================== 关联列表(非数据库字段,用于展示) ====================
|
||||
@Transient
|
||||
var haWbList: List<GjcHaWb>? = null, // 分单列表
|
||||
@Transient
|
||||
var storageUseList: List<GjcStorageUse>? = null, // 库位使用列表
|
||||
@Transient
|
||||
var attachList: List<ComAttach>? = 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属性
|
||||
|
||||
BIN
module_base/src/main/res/mipmap-xhdpi/img_up.png
Normal file
BIN
module_base/src/main/res/mipmap-xhdpi/img_up.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
@@ -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<List<KeyValue>>(emptyList())
|
||||
|
||||
// 运单类型下拉列表
|
||||
val waybillTypeList = MutableLiveData<List<KeyValue>>(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<String, Any> ?: emptyMap()
|
||||
|
||||
// 2. 提取 maWbM 对象(海关扩展数据)
|
||||
val maWbM = data["maWbM"] as? Map<String, Any> ?: emptyMap()
|
||||
|
||||
// 3. 提取 warehouseList(仓库列表,用于计算入库件数和入库重量)
|
||||
val warehouseList = data["warehouseList"] as? List<Map<String, Any>> ?: emptyList()
|
||||
|
||||
// 4. 合并两个对象
|
||||
val mergedData = mutableMapOf<String, Any>()
|
||||
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("修改成功")
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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<GjcMaWb> ?: 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
|
||||
}
|
||||
}
|
||||
|
||||
// 获取统计信息 (后台请求)
|
||||
|
||||
@@ -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) : ``}' />
|
||||
|
||||
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
|
||||
android:layout_width="0dp"
|
||||
@@ -100,7 +100,7 @@
|
||||
title='@{"运单重量"}'
|
||||
titleLength="@{5}"
|
||||
type="@{DataLayoutType.INPUT}"
|
||||
value='@{String.valueOf(viewModel.dataBean.weight)}' />
|
||||
value='@{viewModel.dataBean.weight != null ? String.valueOf(viewModel.dataBean.weight) : ``}' />
|
||||
|
||||
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
|
||||
android:layout_width="0dp"
|
||||
@@ -128,7 +128,7 @@
|
||||
title='@{"入库件数"}'
|
||||
titleLength="@{5}"
|
||||
type="@{DataLayoutType.INPUT}"
|
||||
value='@{String.valueOf(viewModel.dataBean.arrivePc)}' />
|
||||
value='@{viewModel.dataBean.arrivePc != null ? String.valueOf(viewModel.dataBean.arrivePc) : ``}' />
|
||||
|
||||
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
|
||||
android:layout_width="0dp"
|
||||
@@ -138,7 +138,7 @@
|
||||
title='@{"入库重量"}'
|
||||
titleLength="@{5}"
|
||||
type="@{DataLayoutType.INPUT}"
|
||||
value='@{String.valueOf(viewModel.dataBean.arriveWeight)}' />
|
||||
value='@{viewModel.dataBean.arriveWeight != null ? String.valueOf(viewModel.dataBean.arriveWeight) : ``}' />
|
||||
|
||||
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
|
||||
android:layout_width="0dp"
|
||||
@@ -148,7 +148,7 @@
|
||||
title='@{"计费重量"}'
|
||||
titleLength="@{5}"
|
||||
type="@{DataLayoutType.INPUT}"
|
||||
value='@{String.valueOf(viewModel.dataBean.weight)}' />
|
||||
value='@{viewModel.dataBean.weight != null ? String.valueOf(viewModel.dataBean.weight) : ``}' />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -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}' />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -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}' />
|
||||
|
||||
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
enable="@{true}"
|
||||
hint='@{"请输入库位"}'
|
||||
title='@{"库位"}'
|
||||
titleLength="@{5}"
|
||||
type="@{DataLayoutType.INPUT}"
|
||||
value='@={viewModel.dataBean.customsLib}' />
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
android:layout_weight="2" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
<import type="com.lukouguoji.module_base.ui.weight.search.layout.SearchLayoutType" />
|
||||
|
||||
<import type="com.lukouguoji.module_base.R" />
|
||||
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="com.lukouguoji.gjc.viewModel.IntExpArriveViewModel" />
|
||||
@@ -86,6 +88,17 @@
|
||||
android:padding="2dp"
|
||||
android:src="@drawable/img_search" />
|
||||
|
||||
<!-- 全局展开/收起按钮 -->
|
||||
<ImageView
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:onClick="@{()-> viewModel.toggleAllExpand()}"
|
||||
android:padding="2dp"
|
||||
android:scaleType="fitCenter"
|
||||
loadImage="@{viewModel.isAllExpanded ? R.mipmap.img_up : R.mipmap.img_down}"
|
||||
android:contentDescription="展开/收起全部子列表" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -93,13 +93,13 @@
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.8"
|
||||
android:layout_weight="0.7"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
completeSpace="@{4}"
|
||||
completeSpace="@{3}"
|
||||
android:text="重量:" />
|
||||
|
||||
<TextView
|
||||
@@ -120,7 +120,7 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
completeSpace="@{4}"
|
||||
completeSpace="@{5}"
|
||||
android:text="代理人:" />
|
||||
|
||||
<TextView
|
||||
@@ -206,13 +206,13 @@
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.8"
|
||||
android:layout_weight="0.7"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
completeSpace="@{4}"
|
||||
completeSpace="@{3}"
|
||||
android:text="特码:" />
|
||||
|
||||
<TextView
|
||||
|
||||
@@ -339,7 +339,8 @@
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:padding="5dp"
|
||||
android:src="@mipmap/img_down" />
|
||||
android:src="@mipmap/img_down"
|
||||
visible="@{bean.haWbList != null && !bean.haWbList.empty}" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user