feat: 国际出港 出港组装 列表

This commit is contained in:
2026-01-21 11:37:08 +08:00
parent a3fda12fd8
commit 0f1dbe4e05
7 changed files with 746 additions and 16 deletions

View File

@@ -56,18 +56,40 @@ class GjcUldUseBean {
var piClose: String = "" // 探板/收口
var piCloseSize: String = "" // 探板尺寸(CM)
var location: String = "" // 位置
var pieces: String = "" // 件数
var pieces: String = "" // 件数(字符串格式)
var remark: String = "" // 备注
var checkFlag: String = "" // 检查标记
var emptyUld: String = "" // 空ULD
var loadArea: String = "" // 组装区
var pc: Long = 0 // 组装件数
// ========== 出港组装页面扩展字段 ==========
var isExpanded: Boolean = false // 展开状态
var isExpanded: Boolean = false // 展开状态(旧版保留)
@Transient
val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态(Observable)
@Transient
val showMore: ObservableBoolean = ObservableBoolean(false) // 展开状态(Observable)
@Transient
val isLoading: ObservableBoolean = ObservableBoolean(false) // 子列表加载中状态
@Transient
var waybillDetailsLoaded: Boolean = false // 子列表是否已加载过(用于区分"未加载"和"加载后为空"
var waybillDetails: MutableList<GjcWarehouse>? = null // 运单明细缓存
// 子列表是否有数据
val hasWaybillDetails: Boolean
get() = waybillDetails != null && waybillDetails!!.isNotEmpty()
// 是否显示"暂无数据"(已加载但无数据)
val showEmptyView: Boolean
get() = waybillDetailsLoaded && !hasWaybillDetails
// 兼容原有代码的isSelected属性
var isSelected: Boolean
get() = checked.get()
set(value) = checked.set(value)
// 复磅状态文本
val wtStatusText: String
get() = if (wtDate.isNotEmpty()) "已复磅" else "未复磅"
}

View File

@@ -0,0 +1,49 @@
package com.lukouguoji.gjc.holder
import android.view.View
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.databinding.ItemIntExpAssembleBinding
import com.lukouguoji.module_base.adapter.setCommonAdapter
import com.lukouguoji.module_base.base.BaseViewHolder
import com.lukouguoji.module_base.bean.GjcUldUseBean
import com.lukouguoji.module_base.ktx.refresh
/**
* 国际出港-出港组装 列表项ViewHolder
* 参考出港运抵页面的实现
*/
class IntExpAssembleItemViewHolder(view: View) :
BaseViewHolder<GjcUldUseBean, ItemIntExpAssembleBinding>(view) {
override fun onBind(item: Any?, position: Int) {
val bean = getItemBean(item) ?: return
binding.bean = bean
binding.position = position
binding.executePendingBindings()
// 添加图标点击事件 - 切换选择状态
binding.ivIcon.setOnClickListener {
// 反转checked状态
bean.checked.set(!bean.checked.get())
// 立即更新UI图片自动切换
binding.executePendingBindings()
}
// ========== 展开按钮点击事件 ==========
// 通过回调通知ViewModel处理展开逻辑需要加载数据
binding.ivShow.setOnClickListener {
clickListener?.onItemClick(position, 1000) // type=1000表示展开操作
}
// ========== 初始化子列表 RecyclerView ==========
setCommonAdapter(
binding.rvSub,
IntExpAssembleSubViewHolder::class.java,
R.layout.item_int_exp_assemble_sub
)
// 刷新子列表数据
binding.rvSub.refresh(bean.waybillDetails ?: emptyList())
}
}

View File

@@ -0,0 +1,21 @@
package com.lukouguoji.gjc.holder
import android.view.View
import com.lukouguoji.gjc.databinding.ItemIntExpAssembleSubBinding
import com.lukouguoji.module_base.base.BaseViewHolder
import com.lukouguoji.module_base.bean.GjcWarehouse
/**
* 国际出港-出港组装 子列表ViewHolder
* 显示运单明细信息
*/
class IntExpAssembleSubViewHolder(view: View) :
BaseViewHolder<GjcWarehouse, ItemIntExpAssembleSubBinding>(view) {
override fun onBind(item: Any?, position: Int) {
val bean = getItemBean(item) ?: return
binding.bean = bean
binding.position = position + 1 // 序号从1开始
binding.executePendingBindings()
}
}

View File

@@ -7,7 +7,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.alibaba.android.arouter.launcher.ARouter
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.holder.IntExpAssembleViewHolder
import com.lukouguoji.gjc.holder.IntExpAssembleItemViewHolder
import com.lukouguoji.module_base.base.BasePageViewModel
import com.lukouguoji.module_base.bean.GjcUldUseBean
import com.lukouguoji.module_base.http.net.NetApply
@@ -45,8 +45,8 @@ class IntExpAssembleViewModel : BasePageViewModel() {
val assemblerList = MutableLiveData<List<KeyValue>>(emptyList()) // 组装人列表
// ========== 适配器配置 ==========
val itemViewHolder = IntExpAssembleViewHolder::class.java
val itemLayoutId = R.layout.item_int_exp_assemble_uld
val itemViewHolder = IntExpAssembleItemViewHolder::class.java
val itemLayoutId = R.layout.item_int_exp_assemble
// ========== 底部统计 ==========
val totalCount = MutableLiveData("0") // 合计票数
@@ -77,33 +77,54 @@ class IntExpAssembleViewModel : BasePageViewModel() {
/**
* 切换展开/收起状态
* 首次展开时加载运单明细数据
*/
fun toggleExpand(position: Int) {
val bean = pageModel.rv?.commonAdapter()?.getItem(position) as? GjcUldUseBean ?: return
bean.isExpanded = !bean.isExpanded
val isCurrentlyExpanded = bean.showMore.get()
if (bean.isExpanded && bean.waybillDetails == null) {
// 首次展开,加载运单明细
loadWaybillDetails(position, bean)
if (isCurrentlyExpanded) {
// 当前是展开状态,收起
bean.showMore.set(false)
} else {
// 已有数据直接刷新item显示/隐藏
pageModel.rv?.commonAdapter()?.notifyItemChanged(position)
// 当前是收起状态,展开
bean.showMore.set(true)
// 如果未加载过数据,则加载
if (!bean.waybillDetailsLoaded) {
loadWaybillDetails(position, bean)
}
}
}
/**
* 加载运单明细
* 使用接口: /IntExpAssemble/queryAssembledByUld
*/
private fun loadWaybillDetails(position: Int, bean: GjcUldUseBean) {
val params = mapOf("useId" to bean.useId).toRequestBody()
// 设置加载中状态
bean.isLoading.set(true)
pageModel.rv?.commonAdapter()?.notifyItemChanged(position)
launchCollect({ NetApply.api.getIntExpAssembleWaybillDetails(params) }) {
// 构建请求参数 - 传递完整的GjcUldUseBean信息
val params = mapOf(
"useId" to bean.useId,
"uld" to bean.uld,
"fdate" to bean.fdate,
"fno" to bean.fno
).toRequestBody()
launchCollect({ NetApply.api.getAssembledWaybillsByUld(params) }) {
onSuccess = { result ->
bean.waybillDetails = result.data ?: mutableListOf()
bean.waybillDetails = result.data?.toMutableList()
bean.waybillDetailsLoaded = true
bean.isLoading.set(false)
pageModel.rv?.commonAdapter()?.notifyItemChanged(position)
}
onFailed = { _, msg ->
bean.isExpanded = false // 加载失败,恢复展开状态
bean.waybillDetailsLoaded = true // 标记为已加载(即使失败也显示暂无数据)
bean.waybillDetails = mutableListOf() // 设置空列表
bean.isLoading.set(false)
pageModel.rv?.commonAdapter()?.notifyItemChanged(position)
showToast(msg)
}
}

View File

@@ -132,6 +132,8 @@
android:layout_height="match_parent"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
tools:itemCount="3"
tools:listitem="@layout/item_int_exp_assemble_uld" />

View File

@@ -0,0 +1,499 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<variable
name="bean"
type="com.lukouguoji.module_base.bean.GjcUldUseBean" />
<variable
name="position"
type="Integer" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="10dp"
android:orientation="vertical">
<!-- 白色卡片 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_white_radius_8"
android:orientation="vertical">
<!-- 主要内容区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="15dp">
<!-- 选中图标 (飞机图标,根据选择状态切换图片) -->
<ImageView
android:id="@+id/iv_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
loadImage="@{bean.checked.get() ? @drawable/img_plane_s : @drawable/img_plane}"
android:src="@drawable/img_plane" />
<!-- ULD信息区域 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_weight="0.8"
android:orientation="vertical">
<!-- 第一行ULD编码、总重、货重、件数、复磅状态 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- ULD编码 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{5}"
android:text="ULD编码"
android:textColor="@color/text_normal"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.uld}"
android:textColor="@color/colorPrimary"
android:textSize="16sp" />
</LinearLayout>
<!-- 总重 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{4}"
android:text="总重:"
android:textColor="@color/text_normal"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf((int)bean.totalWeight)}"
android:textColor="@color/text_normal"
android:textSize="16sp" />
</LinearLayout>
<!-- 货重 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{4}"
android:text="货重:"
android:textColor="@color/text_normal"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf((int)bean.cargoWeight)}"
android:textColor="@color/text_normal"
android:textSize="16sp" />
</LinearLayout>
<!-- 件数 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{4}"
android:text="件数:"
android:textColor="@color/text_normal"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(bean.pc)}"
android:textColor="@color/text_normal"
android:textSize="16sp" />
</LinearLayout>
<!-- 复磅状态 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{5}"
android:text="复磅状态:"
android:textColor="@color/text_normal"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.wtDate != null &amp;&amp; !bean.wtDate.isEmpty() ? `已复磅` : `未复磅`}"
android:textColor="@{bean.wtDate != null &amp;&amp; !bean.wtDate.isEmpty() ? @color/text_green : @color/text_normal}"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
<!-- 第二行:航班日期、航班号、组装人、组装区、组装时间 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- 航班日期 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{5}"
android:text="航班日期:"
android:textColor="@color/text_normal"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.fdateFormatted}"
android:textColor="@color/text_normal"
android:textSize="16sp" />
</LinearLayout>
<!-- 航班号 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{4}"
android:text="航班号:"
android:textColor="@color/text_normal"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.fno}"
android:textColor="@color/text_normal"
android:textSize="16sp" />
</LinearLayout>
<!-- 组装人 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{4}"
android:text="组装人:"
android:textColor="@color/text_normal"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.ldId}"
android:textColor="@color/text_normal"
android:textSize="16sp" />
</LinearLayout>
<!-- 组装区 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{4}"
android:text="组装区:"
android:textColor="@color/text_normal"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.loadArea}"
android:textColor="@color/text_normal"
android:textSize="16sp" />
</LinearLayout>
<!-- 组装时间 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{5}"
android:text="组装时间:"
android:textColor="@color/text_normal"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.ldDate}"
android:textColor="@color/text_normal"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<!-- 展开按钮 - 始终显示 -->
<ImageView
android:id="@+id/iv_show"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:padding="5dp"
android:rotation="@{bean.showMore.get() ? 180f : 0f}"
android:src="@mipmap/img_down" />
</LinearLayout>
<!-- 子列表容器 -->
<LinearLayout
visible="@{bean.showMore}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:background="#e3f6e0"
android:orientation="vertical"
android:visibility="gone">
<!-- 加载中状态 -->
<LinearLayout
visible="@{bean.isLoading}"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center"
android:orientation="horizontal"
android:visibility="gone">
<ProgressBar
android:layout_width="24dp"
android:layout_height="24dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="加载中..."
android:textColor="@color/text_gray"
android:textSize="14sp" />
</LinearLayout>
<!-- 暂无数据占位UI -->
<TextView
visible="@{bean.showEmptyView &amp;&amp; !bean.isLoading.get()}"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center"
android:text="暂无数据"
android:textColor="@color/text_gray"
android:textSize="14sp"
android:visibility="gone" />
<!-- 表头 (有数据时显示) -->
<LinearLayout
visible="@{bean.hasWaybillDetails &amp;&amp; !bean.isLoading.get()}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="10dp"
android:orientation="horizontal"
android:paddingHorizontal="10dp"
android:visibility="gone">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:gravity="center"
android:text="序号"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:gravity="center"
android:text="运单号"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center"
android:text="件数"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center"
android:text="重量(KG)"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="代理"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="目的港"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="特码"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:gravity="center"
android:text="品名(中)"
android:textColor="@color/text_normal"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
visible="@{bean.hasWaybillDetails &amp;&amp; !bean.isLoading.get()}"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/c999999"
android:visibility="gone" />
<!-- 子列表 RecyclerView (有数据时显示) -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_sub"
visible="@{bean.hasWaybillDetails &amp;&amp; !bean.isLoading.get()}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>
</LinearLayout>
</layout>

View File

@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="bean"
type="com.lukouguoji.module_base.bean.GjcWarehouse" />
<variable
name="position"
type="Integer" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
android:orientation="horizontal"
android:paddingHorizontal="10dp">
<!-- 序号 -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:gravity="center"
android:text="@{String.valueOf(position)}"
android:textColor="@color/text_normal"
android:textSize="14sp" />
<!-- 运单号 -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:gravity="center"
android:text="@{bean.wbNo ?? ``}"
android:textColor="@color/colorPrimary"
android:textSize="14sp"
android:textStyle="bold" />
<!-- 件数 -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center"
android:text="@{String.valueOf(bean.pc)}"
android:textColor="@color/text_normal"
android:textSize="14sp" />
<!-- 重量(KG) -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center"
android:text="@{String.valueOf((int)bean.weight)}"
android:textColor="@color/text_normal"
android:textSize="14sp" />
<!-- 代理 -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@{bean.agentCode ?? ``}"
android:textColor="@color/text_normal"
android:textSize="14sp" />
<!-- 目的港 -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@{bean.dest ?? ``}"
android:textColor="@color/text_normal"
android:textSize="14sp" />
<!-- 特码 -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@{bean.spCode ?? ``}"
android:textColor="@color/text_normal"
android:textSize="14sp" />
<!-- 品名(中) -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:gravity="center"
android:text="@{bean.goodsCn ?? ``}"
android:textColor="@color/text_normal"
android:textSize="14sp" />
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/c999999" />
</LinearLayout>
</layout>