merge: 手机适配分支 feature/phone-ui-adaptation 合入 main,平板与 5.5 寸手机统一在主干开发

合并原则:业务层以 main 平板为准,手机端只做 UI 适配。
- 冲突布局:平板改动三方合并进 layout-sw600dp/,手机布局保留并补齐主干新增业务
- Bean/ViewModel 冲突取平板业务逻辑(计重托盘联动、开始计重运抵重量自动计算、
  出港查询 dateState、仓库入/出库件数重量、清仓备注等),手机仅保留展示字段
- 主干新功能同步到手机:运抵海关放行/分单号筛选/回执走 getResponse、删除申报;
  出库交接装机状态与允许装机/配运;出港移库详情与编辑共用 IntExpMoveEditActivity;
  出入港仓库清仓备注、出库弹框件数重量、进港仓库 pcLabel;ULD 所在港/位置
- 新增手机变体:出库/入库/清仓/配运/删除申报弹框、移库详情编辑页、海关回执页;
  PhoneBottomBar 增次操作按钮
- 手机对齐平板:去掉 likeNo 与平板没有的筛选入参、恢复平板默认查询日期,
  补齐平板表单/筛选项与操作入口;移除手机专属 IntExpMoveDetailActivity
- CLAUDE.md 记录单分支约定与「业务以平板为准」规则,CHANGELOG 补合并记录

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
YANG JIANKUAN
2026-10-11 21:20:03 -07:00
356 changed files with 44711 additions and 13385 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
package com.lukouguoji.aerologic.page.gnj.move.stash.detail
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.google.gson.Gson
import com.lukouguoji.aerologic.R
import com.lukouguoji.aerologic.databinding.ActivityGnjMoveStashDetailBinding
import com.lukouguoji.aerologic.page.gnj.move.stash.photo.GnjMoveStashPhotoActivity
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.bean.MoveStashBean
import com.lukouguoji.module_base.common.Constant
/**
* 国内进港移库「运单详情」(5.5 寸手持端专属页面,无平板变体)
*
* 由列表卡片的「查看详情」进入;「异常照片」卡片的加号槽位跳拍照上传页。
* 展示字段全部由列表项带入(Gson JSON),零新增请求。
*/
class GnjMoveStashDetailActivity :
BaseBindingActivity<ActivityGnjMoveStashDetailBinding, GnjMoveStashDetailViewModel>() {
override fun layoutId() = R.layout.activity_gnj_move_stash_detail
override fun viewModelClass() = GnjMoveStashDetailViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("运单详情")
binding.viewModel = viewModel
binding.activity = this
viewModel.initOnCreated(intent)
}
/** 「异常照片」加号槽位 → 拍照上传页 */
fun openPhoto() {
viewModel.dataBean.value?.let {
GnjMoveStashPhotoActivity.start(this, it.mawbId, it.wbNo, it.moveId)
}
}
companion object {
@JvmStatic
fun start(context: Context, bean: MoveStashBean) {
context.startActivity(
Intent(context, GnjMoveStashDetailActivity::class.java)
.putExtra(Constant.Key.DATA, Gson().toJson(bean))
)
}
}
}

View File

@@ -0,0 +1,25 @@
package com.lukouguoji.aerologic.page.gnj.move.stash.detail
import android.content.Intent
import androidx.lifecycle.MutableLiveData
import com.google.gson.Gson
import com.lukouguoji.module_base.base.BaseViewModel
import com.lukouguoji.module_base.bean.MoveStashBean
import com.lukouguoji.module_base.common.Constant
/**
* 国内进港移库「运单详情」ViewModel(5.5 寸手持端专属页面)
*
* 列表项数据已包含详情页所需全部字段(含 isMoved 端点打标),直接由列表带入,不额外请求。
*/
class GnjMoveStashDetailViewModel : BaseViewModel() {
val dataBean = MutableLiveData(MoveStashBean())
fun initOnCreated(intent: Intent) {
val json = intent.getStringExtra(Constant.Key.DATA).orEmpty()
if (json.isNotEmpty()) {
dataBean.value = Gson().fromJson(json, MoveStashBean::class.java)
}
}
}

View File

@@ -1,36 +1,102 @@
package com.lukouguoji.aerologic.page.gnj.move.stash.list
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.lukouguoji.aerologic.R
import com.lukouguoji.aerologic.databinding.ActivityGnjMoveStashListBinding
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.ktx.getLifecycleOwner
class GnjMoveStashListActivity :
BaseBindingActivity<ActivityGnjMoveStashListBinding, GnjMoveStashListViewModel>() {
override fun layoutId() = R.layout.activity_gnj_move_stash_list
override fun viewModelClass() = GnjMoveStashListViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("国内进港移库")
binding.viewModel = viewModel
viewModel.pageModel
.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner())
viewModel.refresh()
}
companion object {
@JvmStatic
fun start(context: Context) {
val starter = Intent(context, GnjMoveStashListActivity::class.java)
context.startActivity(starter)
}
}
}
package com.lukouguoji.aerologic.page.gnj.move.stash.list
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.databinding.ObservableBoolean
import com.alibaba.android.arouter.facade.annotation.Route
import com.lukouguoji.aerologic.R
import com.lukouguoji.aerologic.databinding.ActivityGnjMoveStashListBinding
import com.lukouguoji.aerologic.page.gnj.move.stash.photo.GnjMoveStashPhotoActivity
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.bean.MoveStashBean
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.getLifecycleOwner
import com.lukouguoji.module_base.router.ARouterConstants
import com.lukouguoji.module_base.util.DeviceUtil
@Route(path = ARouterConstants.ACTIVITY_URL_GNJ_MOVE_STASH_LIST)
class GnjMoveStashListActivity :
BaseBindingActivity<ActivityGnjMoveStashListBinding, GnjMoveStashListViewModel>() {
override fun layoutId() = R.layout.activity_gnj_move_stash_list
override fun viewModelClass() = GnjMoveStashListViewModel::class.java
/** 筛选弹层显隐(仅手机 UI 状态,平板布局不绑定) */
val filterPanelVisible = ObservableBoolean(false)
override fun initOnCreate(savedInstanceState: Bundle?) {
// 设计稿手机端标题为「进港移库」,平板保持原标题
setBackArrow(if (DeviceUtil.isPhone()) "进港移库" else "国内进港移库")
binding.viewModel = viewModel
binding.activity = this
viewModel.pageModel
.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner())
if (DeviceUtil.isPhone()) {
// 手机专属:Tab 角标 + 特码字典等额外请求
viewModel.initPhoneExtras()
// 卡片勾选变化 → 更新全选状态与已选计数
FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) {
viewModel.updateCheckAllStatus()
}
}
// 拍照上传等子页面完成后刷新列表(平板无发射方,观察无副作用)
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).observe(this) {
viewModel.refresh()
}
viewModel.refresh()
}
// ==================== 筛选弹层(仅手机) ====================
fun toggleFilterPanel() {
filterPanelVisible.set(!filterPanelVisible.get())
}
/** 筛选:重置(只清空弹层内条件,不影响 Tab 与顶部搜索框) */
fun resetFilter() {
viewModel.carrier.value = ""
viewModel.businessType.value = ""
}
fun confirmFilter() {
filterPanelVisible.set(false)
viewModel.refresh()
}
// ==================== 卡片长按「拍照」浮层(仅手机) ====================
/** 卡片长按:展开操作浮层(View.OnLongClickListener 要求返回 Boolean) */
fun showCardActionPhone(bean: MoveStashBean): Boolean {
bean.actionMenuVisible.set(true)
return true
}
/** 点浮层空白处关闭 */
fun hideCardActionPhone(bean: MoveStashBean) {
bean.actionMenuVisible.set(false)
}
/** 浮层「拍照」→ 拍照上传页 */
fun openPhoto(bean: MoveStashBean) {
bean.actionMenuVisible.set(false)
GnjMoveStashPhotoActivity.start(this, bean.mawbId, bean.wbNo, bean.moveId)
}
companion object {
@JvmStatic
fun start(context: Context) {
val starter = Intent(context, GnjMoveStashListActivity::class.java)
context.startActivity(starter)
}
}
}

View File

@@ -3,34 +3,64 @@ package com.lukouguoji.aerologic.page.gnj.move.stash.list
import android.view.View
import android.widget.Toast
import com.lukouguoji.aerologic.databinding.ItemGnjMoveStashListBinding
import com.lukouguoji.aerologic.page.gnj.move.stash.detail.GnjMoveStashDetailActivity
import com.lukouguoji.gnj.page.yiku.handover.GnjYiKuHandoverActivity
import com.lukouguoji.module_base.base.BaseViewHolder
import com.lukouguoji.module_base.bean.MoveStashBean
import com.lukouguoji.module_base.common.ConstantEvent
import com.lukouguoji.module_base.impl.FlowBus
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
/**
* 国内进港移库列表项 ViewHolder(双形态共用)
*
* 平板/手机布局差异较大,单侧独有的控件 id 在 Binding 基类中为 @Nullable,
* 全部走判空调用(平板:swipe_menu/btn_edit/ll;手机:ll_detail)。
*/
class GnjMoveStashListViewHolder(view: View) :
BaseViewHolder<MoveStashBean, ItemGnjMoveStashListBinding>(view) {
override fun onBind(item: Any?, position: Int) {
val bean = getItemBean(item)!!
binding.bean = bean
binding.position = position
binding.activity = itemView.context as? GnjMoveStashListActivity
// 勾选框(双形态共有):切换选中;手机端另行广播刷新全选/已选计数
binding.ivIcon.setOnClickListener {
bean.checked.set(!bean.checked.get())
binding.executePendingBindings()
GlobalScope.launch {
FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED).emit("check_changed")
}
}
// ===== 平板独有交互 =====
// 点击列表项进入移交详情
binding.ll.setOnClickListener {
binding.ll?.setOnClickListener {
GnjYiKuHandoverActivity.startForDetails(itemView.context, bean.mawbId)
}
// 侧滑菜单 - 编辑按钮
binding.btnEdit.setOnClickListener {
binding.swipeMenu.quickClose()
binding.btnEdit?.setOnClickListener {
binding.swipeMenu?.quickClose()
if (bean.pickFlag == "1") {
Toast.makeText(itemView.context, "已出库,不可编辑", Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
GnjYiKuHandoverActivity.startForEdit(itemView.context, bean.mawbId)
}
// ===== 手机独有交互 =====
// 「查看详情」→ 手机版运单详情页
binding.llDetail?.setOnClickListener {
GnjMoveStashDetailActivity.start(itemView.context, bean)
}
binding.executePendingBindings()
}
}

View File

@@ -49,6 +49,31 @@ class GnjMoveStashListViewModel : BasePageViewModel() {
val number = MutableLiveData("0")
val weight = MutableLiveData("0")
// ========== 5.5 寸手持端专属字段(平板布局不绑定,默认值保证平板行为零变化) ==========
/** 移库状态 Tab:"0" 待移库(DomImpMove/search)/ "1" 已移库(DomImpMove/searchMoved) */
val moveState = MutableLiveData("0")
val moveStateTabs = MutableLiveData(
listOf(KeyValue("待移库", "0"), KeyValue("已移库", "1"))
)
/** 状态 Tab 角标(与 [moveStateTabs] 等长,取两端点分页 total) */
val moveStateCounts = MutableLiveData(listOf("", ""))
/** 底部操作条「已选 N 项」 */
val selectedCount = MutableLiveData("0")
/** 全选状态(手机 PhoneBottomBar 勾选图标) */
val isAllChecked = MutableLiveData(false)
/** 手机专属的额外请求(Tab 角标)开关,仅手机形态在 Activity 中开启 */
private var phoneExtrasEnabled = false
fun initPhoneExtras() {
phoneExtrasEnabled = true
}
///////////////////////////////////////////////////////////////////////////
// 方法区
///////////////////////////////////////////////////////////////////////////
@@ -95,25 +120,69 @@ class GnjMoveStashListViewModel : BasePageViewModel() {
}
/** 查询条件(分页参数除外),search / searchMoved / searchTotal 三处共用同一套入参 */
private fun buildFilterParams(): Map<String, Any?> = mapOf(
"awbType" to businessType.value!!.ifEmpty { null },
"wbNo" to waybill.value!!.ifEmpty { null },
"carrier" to carrier.value!!.ifEmpty { null },
)
override fun getData() {
val body = mapOf(
val body = (buildFilterParams() + mapOf(
"page" to pageModel.page,
"limit" to pageModel.limit,
"awbType" to businessType.value!!.ifEmpty { null },
"wbNo" to waybill.value!!.ifEmpty { null },
"carrier" to carrier.value!!.ifEmpty { null },
).toRequestBody()
)).toRequestBody()
val moved = moveState.value == "1"
launchLoadingCollect({
NetApply.api.getGnjMoveStashList(
body
)
// 平板 moveState 恒为 "0" → 恒走 search(原行为);已移库 Tab 走 searchMoved
if (moved) NetApply.api.getGnjMoveStashMovedList(body)
else NetApply.api.getGnjMoveStashList(body)
}) {
onSuccess = {
pageModel.handleListBean(it)
// searchMoved 出参无移库标识,按端点打标(卡片形态/详情移库信息卡依赖)
it.list?.forEach { bean -> bean.isMoved = moved }
pageModel.handleListBean(it) { updateCheckAllStatus() }
count.value = it.total
}
}
getCountData(body)
if (phoneExtrasEnabled) loadTabCounts()
}
/** Tab 角标:search / searchMoved 各以 limit=1 查一次取分页 total(仅手机形态发起) */
private fun loadTabCounts() {
val body = (buildFilterParams() + mapOf("page" to 1, "limit" to 1)).toRequestBody()
launchCollect({ NetApply.api.getGnjMoveStashList(body) }) {
onSuccess = { updateTabCount(0, it.total) }
}
launchCollect({ NetApply.api.getGnjMoveStashMovedList(body) }) {
onSuccess = { updateTabCount(1, it.total) }
}
}
private fun updateTabCount(index: Int, total: Int?) {
val current = moveStateCounts.value?.toMutableList() ?: mutableListOf("", "")
if (index < current.size) {
current[index] = (total ?: 0).toString()
moveStateCounts.value = current
}
}
// ========== 手机端全选 / 已选计数 ==========
fun toggleSelectAll() {
val list = pageModel.rv?.commonAdapter()?.items
?.filterIsInstance<MoveStashBean>() ?: return
CheckUtil.handleAllCheck(list)
updateCheckAllStatus()
pageModel.rv?.commonAdapter()?.notifyDataSetChanged()
}
fun updateCheckAllStatus() {
val list = pageModel.rv?.commonAdapter()?.items
?.filterIsInstance<MoveStashBean>() ?: return
isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() }
selectedCount.value = list.count { it.checked.get() }.toString()
}
private fun getCountData(body: RequestBody) {

View File

@@ -0,0 +1,49 @@
package com.lukouguoji.aerologic.page.gnj.move.stash.photo
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.lukouguoji.aerologic.R
import com.lukouguoji.aerologic.databinding.ActivityGnjMoveStashPhotoBinding
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.ktx.addOnItemClickListener
/**
* 国内进港移库「拍照上传」(5.5 寸手持端专属页面,无平板变体)
*
* 由列表卡片长按浮层「拍照」或运单详情「异常照片」加号槽位进入。
* 已有照片经 DomImpMove/detail 回填,提交走 DomImpMove/modify
* (mawbId + pic/originalPic/picNumber 三字段规范,与平板移交编辑页同一链路)。
*/
class GnjMoveStashPhotoActivity :
BaseBindingActivity<ActivityGnjMoveStashPhotoBinding, GnjMoveStashPhotoViewModel>() {
override fun layoutId() = R.layout.activity_gnj_move_stash_photo
override fun viewModelClass() = GnjMoveStashPhotoViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("拍照上传")
binding.viewModel = viewModel
viewModel.rv = binding.rv
binding.rv.addOnItemClickListener(viewModel)
viewModel.initOnCreated(intent)
}
companion object {
/** 已移库运单的 moveId(movedDetail 回填照片用) */
const val EXTRA_MOVE_ID = "moveId"
@JvmStatic
fun start(context: Context, mawbId: String, wbNo: String, moveId: String = "") {
context.startActivity(
Intent(context, GnjMoveStashPhotoActivity::class.java)
.putExtra(Constant.Key.ID, mawbId)
.putExtra(Constant.Key.CODE, wbNo)
.putExtra(EXTRA_MOVE_ID, moveId)
)
}
}
}

View File

@@ -0,0 +1,188 @@
package com.lukouguoji.aerologic.page.gnj.move.stash.photo
import android.content.Intent
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import androidx.recyclerview.widget.RecyclerView
import com.lukouguoji.module_base.base.BaseViewModel
import com.lukouguoji.module_base.bean.FileBean
import com.lukouguoji.module_base.bean.GnjYiKuBean
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.impl.ImageSelectNewViewHolder
import com.lukouguoji.module_base.interfaces.IOnItemClickListener
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.noNull
import com.lukouguoji.module_base.ktx.showToast
import com.lukouguoji.module_base.ktx.toRequestBody
import com.lukouguoji.module_base.util.MediaUtil
import com.lukouguoji.module_base.util.UploadUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
/**
* 国内进港移库「拍照上传」ViewModel(5.5 寸手持端专属页面)
*
* 图片选择/预览/删除复用 module_base 的 ImageSelectNewViewHolder(末位加号槽位)。
* 已有照片回填:待移库经 DomImpMove/detail(mawbId),已移库经 DomImpMove/movedDetail(moveId,
* searchMoved 出参不含 mawbId)。提交走 DomImpMove/modify 最小体
* (mawbId/remark/picNumber/pic/originalPic),与平板移交编辑页同一链路。
*/
class GnjMoveStashPhotoViewModel : BaseViewModel(), IOnItemClickListener {
var mawbId = ""
/** 已移库运单的移库记录 ID(searchMoved 出参),用于 movedDetail 回填 */
var moveId = ""
/** 运单号(副标题展示,由列表带入) */
val wbNo = MutableLiveData("")
/** detail 回填的完整 bean(提交时保留 remark 等原值) */
private var detailBean = GnjYiKuBean()
// 图片网格适配器配置(复用公共图片选择组件)
val itemViewHolder = ImageSelectNewViewHolder::class.java
val itemLayoutId = com.lukouguoji.module_base.R.layout.item_image_select_new
var rv: RecyclerView? = null
fun initOnCreated(intent: Intent) {
mawbId = intent.getStringExtra(Constant.Key.ID).orEmpty()
wbNo.value = intent.getStringExtra(Constant.Key.CODE).orEmpty()
moveId = intent.getStringExtra(GnjMoveStashPhotoActivity.EXTRA_MOVE_ID).orEmpty()
// 已有照片回填(pic 缩略图 + originalPic 原图),末位补加号槽位;
// 已移库运单无 mawbId,改按 moveId 走 movedDetail
launchCollect({
if (mawbId.isEmpty() && moveId.isNotEmpty()) NetApply.api.getGnjMoveStashMovedDetail(moveId)
else NetApply.api.getGnjMoveStashDetail(mawbId)
}) {
onSuccess = {
detailBean = it.data ?: GnjYiKuBean()
val picList = detailBean.pic.split(",").filter { p -> p.isNotEmpty() }
val originalList = detailBean.originalPic.split(",").filter { p -> p.isNotEmpty() }
val images = picList.mapIndexed { index, picUrl ->
FileBean(
path = MediaUtil.fillUrl(picUrl),
url = picUrl,
originalPic = MediaUtil.fillUrl(originalList.getOrElse(index) { picUrl })
)
}
rv?.post {
rv?.commonAdapter()?.refresh(images + FileBean())
}
}
onFailed = { _, _ ->
// 详情取不到也允许直接新增照片
rv?.post { rv?.commonAdapter()?.refresh(listOf(FileBean())) }
}
}
}
/**
* 确认提交:先补传未上传的本地图片,再按三字段规范提交 modify
*/
fun submitClick() {
// modify 以 mawbId 定位运单;已移库运单 searchMoved/movedDetail 均不返回 mawbId(后端缺口),无法提交
if (mawbId.isEmpty()) {
showToast("已移库运单缺少运单ID,暂不支持提交照片")
return
}
(rv?.commonAdapter()?.items ?: emptyList())
.asFlow()
.map { it as FileBean }
.filter { it.path.isNotEmpty() && it.url.isEmpty() }
.onEach {
val data = UploadUtil.upload(it.path).data
// UploadUtil 返回:newName=原图(较大),zipFileName=缩略图(较小)
it.url = data?.zipFileName ?: ""
it.originalPic = data?.newName ?: ""
}
.flowOn(Dispatchers.IO)
.onStart { showLoading() }
.catch {
showToast(it.message.noNull("上传图片失败"))
dismissLoading()
}
.onCompletion {
launchLoadingCollect({
val list = (rv?.commonAdapter()?.items ?: emptyList())
.filterIsInstance<FileBean>()
.filter { it.path.isNotEmpty() }
// 最小体提交:只更新图片三字段(remark 保留 detail 原值),与平板移交编辑页一致
val params = mapOf(
"mawbId" to mawbId,
"remark" to detailBean.remark,
"picNumber" to list.size.toString(),
"pic" to list.joinToString(",") { MediaUtil.removeUrl(it.url) },
"originalPic" to list.joinToString(",") { MediaUtil.removeUrl(it.originalPic) },
).toRequestBody(removeEmptyOrNull = true)
NetApply.api.modifyGnjMoveStash(params)
}) {
onSuccess = {
showToast("提交成功")
viewModelScope.launch {
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).emit("refresh")
}
getTopActivity().finish()
}
onFailed = { _, msg ->
showToast(msg.noNull("提交失败"))
}
}
}
.launchIn(viewModelScope)
}
/**
* 「拍照/上传」按钮:直接唤起图片选择(含拍照入口)
*/
fun pickClick() {
MediaUtil.pickImage(getTopActivity(), maxNum = 9) { results ->
val adapter = rv?.commonAdapter() ?: return@pickImage
results.forEach { result ->
// 在加号槽位(最后一项)之前插入
val insertPos = (adapter.items.size - 1).coerceAtLeast(0)
adapter.items.add(insertPos, FileBean(path = result.realPath))
adapter.notifyItemInserted(insertPos)
}
}
}
/**
* 图片网格点击回调(长按出删除角标 / 点删除角标移除)
*/
override fun onItemClick(position: Int, type: Int) {
val adapter = rv?.commonAdapter() ?: return
val bean = adapter.getItem(position) as? FileBean ?: return
when (type) {
com.lukouguoji.module_base.R.id.rl -> {
if (bean.path.isNotEmpty()) {
bean.canDelete.set(!bean.canDelete.get())
}
}
com.lukouguoji.module_base.R.id.iv_delete -> {
adapter.removeItem(position)
}
else -> {}
}
}
}

View File

@@ -19,6 +19,7 @@ import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.bean.LogBean
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.router.ARouterConstants
import com.lukouguoji.module_base.util.DeviceUtil
@Route(path = ARouterConstants.ACTIVITY_URL_LOG_DETAIL)
class LogDetailActivity : BaseBindingActivity<ActivityLogDetailBinding, LogDetailViewModel>() {
@@ -34,7 +35,8 @@ class LogDetailActivity : BaseBindingActivity<ActivityLogDetailBinding, LogDetai
}
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("操作日志详情")
// 手机版设计稿标题为「运单追踪」,平板保持原标题
setBackArrow(if (DeviceUtil.isPhone()) "运单追踪" else "操作日志详情")
binding.viewModel = viewModel
// 配置操作详情 RecyclerView(垂直时间线)
@@ -58,7 +60,139 @@ class LogDetailActivity : BaseBindingActivity<ActivityLogDetailBinding, LogDetai
val activeCodes = viewModel.activeStepCodes.value ?: emptySet()
val latestCode = viewModel.latestStepCode.value ?: ""
if (steps.isEmpty()) return
buildStepProgressBar(steps, activeCodes, latestCode)
// 手机布局是竖排时间线(layout/activity_log_detail.xml),平板保持横向步骤条
if (DeviceUtil.isPhone()) {
buildVerticalSteps(steps, activeCodes, latestCode)
} else {
buildStepProgressBar(steps, activeCodes, latestCode)
}
}
/**
* 手机版竖排流转时间线(对应设计稿「运单追踪」):
* 每个节点 = 左侧圆点 + 连接竖线,右侧步骤名 + 该环节最新操作时间。
* 已发生节点绿色,未发生节点灰色。
*/
private fun buildVerticalSteps(
steps: List<StepInfo>,
activeCodes: Set<String>,
latestCode: String
) {
val container = binding.llSteps
container.removeAllViews()
container.orientation = LinearLayout.VERTICAL
val logs = viewModel.statusLogList.value ?: emptyList()
val colorGreen = 0xFF16A34A.toInt()
val colorGray = 0xFF9CA3AF.toInt()
val colorLine = 0xFFE5E7EB.toInt()
for (i in steps.indices) {
val step = steps[i]
val isActive = step.code in activeCodes
val isLast = i == steps.size - 1
val stepLog = logs.lastOrNull { it.status == step.code }
val time = stepLog?.opDate ?: ""
val statusContent = stepLog?.content ?: ""
val row = LinearLayout(this).apply {
orientation = LinearLayout.HORIZONTAL
layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
}
// 左列:圆点 + 连接竖线
val dotColumn = LinearLayout(this).apply {
orientation = LinearLayout.VERTICAL
gravity = Gravity.CENTER_HORIZONTAL
layoutParams = LinearLayout.LayoutParams(dp(20), LinearLayout.LayoutParams.MATCH_PARENT)
}
val dot = View(this).apply {
setBackgroundResource(
if (isActive) com.lukouguoji.module_base.R.drawable.bg_phone_dot_green
else com.lukouguoji.module_base.R.drawable.bg_phone_dot_gray
)
layoutParams = LinearLayout.LayoutParams(
dp(if (isActive) 12 else 8), dp(if (isActive) 12 else 8)
).apply { topMargin = dp(if (isActive) 2 else 4) }
}
dotColumn.addView(dot)
if (!isLast) {
val line = View(this).apply {
setBackgroundColor(colorLine)
layoutParams = LinearLayout.LayoutParams(dp(2), 0).apply {
weight = 1f
topMargin = dp(2)
bottomMargin = dp(2)
}
}
dotColumn.addView(line)
}
row.addView(dotColumn)
// 右列:步骤名 + 时间
val content = LinearLayout(this).apply {
orientation = LinearLayout.VERTICAL
layoutParams = LinearLayout.LayoutParams(
0, LinearLayout.LayoutParams.WRAP_CONTENT
).apply {
weight = 1f
leftMargin = dp(10)
}
setPadding(0, 0, 0, if (isLast) 0 else dp(24))
}
// 名称行:步骤名(左)+ 已发生节点的状态 pill(右,设计稿如「放行状态:01」)
val nameRow = LinearLayout(this).apply {
orientation = LinearLayout.HORIZONTAL
gravity = Gravity.CENTER_VERTICAL
layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
}
nameRow.addView(TextView(this).apply {
text = step.name
setTextSize(TypedValue.COMPLEX_UNIT_SP, 15f)
setTextColor(if (isActive) colorGreen else colorGray)
if (isActive) setTypeface(typeface, android.graphics.Typeface.BOLD)
layoutParams = LinearLayout.LayoutParams(
0, LinearLayout.LayoutParams.WRAP_CONTENT
).apply { weight = 1f }
})
if (isActive && statusContent.isNotEmpty()) {
nameRow.addView(TextView(this).apply {
text = statusContent
setTextSize(TypedValue.COMPLEX_UNIT_SP, 11f)
setTextColor(colorGreen)
setBackgroundResource(com.lukouguoji.module_base.R.drawable.bg_phone_tag_green)
setPadding(dp(8), dp(3), dp(8), dp(3))
maxLines = 1
ellipsize = android.text.TextUtils.TruncateAt.END
maxWidth = dp(180)
layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
).apply { leftMargin = dp(8) }
})
}
content.addView(nameRow)
if (time.isNotEmpty()) {
content.addView(TextView(this).apply {
text = time
setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f)
setTextColor(colorGray)
layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
).apply { topMargin = dp(4) }
})
}
row.addView(content)
container.addView(row)
}
}
private fun buildStepProgressBar(

View File

@@ -7,7 +7,15 @@ import com.lukouguoji.aerologic.R
import com.lukouguoji.aerologic.databinding.ActivityUldEditBinding
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.common.DetailsPageType
import com.lxj.xpopup.XPopup
/**
* ULD 新增 / 修改 / 详情(一页三态,标题按 pageType 切换)。
*
* 布局 id 不区分设备,平板/手机由资源限定符自动选择:
* layout-sw600dp/activity_uld_edit.xml(平板) / layout/activity_uld_edit.xml(手机)
*/
class UldEditActivity : BaseBindingActivity<ActivityUldEditBinding, UldEditViewModel>() {
override fun layoutId() = R.layout.activity_uld_edit
@@ -18,6 +26,26 @@ class UldEditActivity : BaseBindingActivity<ActivityUldEditBinding, UldEditViewM
viewModel.initOnCreate(intent)
setBackArrow("ULD${viewModel.pageType.value!!.title}")
binding.viewModel = viewModel
binding.activity = this
}
// ==================== 手机版专用交互(纯 UI) ====================
/** 详情态右上铅笔 → 关闭详情并进入修改页 */
fun onEditClick() {
start(this, viewModel.id, modify = true)
finish()
}
/** 状态行点击 → 底部选择面板(详情态只读不弹) */
fun onStatusRowClick() {
if (viewModel.pageType.value == DetailsPageType.Details) return
val options = viewModel.statusPhoneList
XPopup.Builder(this)
.asBottomList("请选择状态", options.map { it.key }.toTypedArray()) { position, _ ->
options.getOrNull(position)?.let { viewModel.onStatusSelected(it.value) }
}
.show()
}
companion object {

View File

@@ -11,6 +11,7 @@ import com.lukouguoji.module_base.ktx.launchLoadingCollect
import com.lukouguoji.module_base.ktx.noNull
import com.lukouguoji.module_base.ktx.showToast
import com.lukouguoji.module_base.ktx.toRequestBody
import com.lukouguoji.module_base.util.DeviceUtil
import com.lukouguoji.module_base.util.DictUtils
import dev.DevUtils
import dev.utils.app.info.KeyValue
@@ -41,6 +42,17 @@ class UldEditViewModel : BaseViewModel() {
// 所属航司下拉列表(数据源:POST /typeCode/intCarrier)
val carrierList = MutableLiveData<List<KeyValue>>(emptyList())
// ========== 手机版(5.5 寸手持端)专用 ==========
/**
* 手机版状态选项。后端枚举维持两态(0 正常 / 1 故障,不新增「占用」),
* 按设计稿文案映射 可用=0 / 维修=1。
*/
val statusPhoneList = listOf(
KeyValue("可用", "0"),
KeyValue("维修", "1"),
)
fun initOnCreate(intent: Intent) {
id = intent.getStringExtra(Constant.Key.ID) ?: ""
val modify = intent.getBooleanExtra(Constant.Key.DATA, false)
@@ -56,6 +68,11 @@ class UldEditViewModel : BaseViewModel() {
}
}
/** 手机版状态行选中回调(copy 重新赋值以触发标签样式刷新) */
fun onStatusSelected(statusValue: String) {
uldBean.value = uldBean.value?.copy(status = statusValue)
}
private fun getData() {
if (id.isEmpty()) return
launchLoadingCollect({
@@ -81,6 +98,10 @@ class UldEditViewModel : BaseViewModel() {
showToast("ULD编号不能为空")
return
}
// 手机版日期行只产出 yyyy-MM-dd,而 inStoreTime 为 date-time(仅日期后端返回 400),补齐时分秒
if (DeviceUtil.isPhone() && bean.inStoreTime.length == 10) {
bean.inStoreTime = "${bean.inStoreTime} 00:00:00"
}
val isAdd = pageType.value == DetailsPageType.Add
launchLoadingCollect({
if (isAdd) NetApply.api.saveUld(bean.toRequestBody())

View File

@@ -3,12 +3,27 @@ package com.lukouguoji.aerologic.page.uld.list
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.databinding.ObservableBoolean
import com.alibaba.android.arouter.facade.annotation.Route
import com.lukouguoji.aerologic.R
import com.lukouguoji.aerologic.databinding.ActivityUldListBinding
import com.lukouguoji.module_base.base.BaseBindingActivity
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.ktx.getLifecycleOwner
import com.lukouguoji.module_base.ktx.showToast
import com.lukouguoji.module_base.model.ConfirmDialogModel
import com.lukouguoji.module_base.router.ARouterConstants
/**
* ULD管理列表页。
*
* 布局 id 不区分设备,平板/手机由资源限定符自动选择:
* layout-sw600dp/activity_uld_list.xml(平板) / layout/activity_uld_list.xml(手机)
*/
@Route(path = ARouterConstants.ACTIVITY_URL_ULD_LIST)
class UldListActivity : BaseBindingActivity<ActivityUldListBinding, UldListViewModel>() {
override fun layoutId(): Int {
@@ -19,9 +34,13 @@ class UldListActivity : BaseBindingActivity<ActivityUldListBinding, UldListViewM
return UldListViewModel::class.java
}
/** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */
val filterPanelVisible = ObservableBoolean(false)
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("ULD管理")
binding.viewModel = viewModel
binding.activity = this
viewModel.pageModel.bindSmartRefreshLayout(
binding.srl,
binding.rv,
@@ -29,6 +48,11 @@ class UldListActivity : BaseBindingActivity<ActivityUldListBinding, UldListViewM
getLifecycleOwner()
)
binding.rv.addOnItemClickListener(viewModel)
// 手机版卡片勾选变化 → 刷新全选与已选统计(平板 item 无勾选框,不会触发)
FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) {
viewModel.onItemCheckChanged()
}
}
override fun onResume() {
@@ -36,6 +60,44 @@ class UldListActivity : BaseBindingActivity<ActivityUldListBinding, UldListViewM
viewModel.refresh()
}
// ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 字段) ====================
/** 手机版筛选弹层显隐切换 */
fun toggleFilterPanel() {
filterPanelVisible.set(!filterPanelVisible.get())
}
/**
* 手机版筛选:重置
*
* 只清空弹层内的两个条件(状态 / 所属航司),不影响顶部搜索框。
*/
fun resetFilter() {
viewModel.status.value = ""
viewModel.uldSuffix.value = ""
}
/** 手机版筛选:确认 */
fun confirmFilter() {
filterPanelVisible.set(false)
viewModel.refresh()
}
/** 手机版批量删除(二次确认后调用批量删除接口) */
fun showDeleteConfirmDialog() {
val selected = viewModel.getSelectedItems()
if (selected.isEmpty()) {
showToast("请选择要删除的ULD")
return
}
ConfirmDialogModel(
message = "确定要删除选中的 ${selected.size} 条ULD记录吗?",
title = "删除确认"
) {
viewModel.deleteSelected()
}.show()
}
companion object {
@JvmStatic
fun start(context: Context) {

View File

@@ -4,13 +4,35 @@ import android.view.View
import com.lukouguoji.aerologic.databinding.ItemUldListBinding
import com.lukouguoji.module_base.base.BaseViewHolder
import com.lukouguoji.module_base.bean.ULDBean
import com.lukouguoji.module_base.common.ConstantEvent
import com.lukouguoji.module_base.impl.FlowBus
/**
* ULD管理列表项 ViewHolder。
*
* 平板 / 手机共用:布局按资源限定符切换,本类不做设备判断。
* 平板独有 id(tv_modify / tv_delete 侧滑按钮)与手机独有 id(iv_check 勾选框)
* 在 Binding 基类中为 @Nullable,各自判空使用。
*/
class UldListViewHolder(view: View) : BaseViewHolder<ULDBean, ItemUldListBinding>(view) {
override fun onBind(item: Any?, position: Int) {
val itemBean = getItemBean(item)!!
binding.bean = itemBean
// 点卡片进详情(两端共用,走 ViewModel.onItemClick 的 R.id.ll_content 分支)
notifyItemClick(position, binding.llContent)
notifyItemClick(position, binding.tvModify)
notifyItemClick(position, binding.tvDelete)
// 平板侧滑按钮(手机变体无此控件)
binding.tvModify?.let { notifyItemClick(position, it) }
binding.tvDelete?.let { notifyItemClick(position, it) }
// 手机版勾选框(平板变体无此控件):切换选中态并通知页面刷新全选/已选统计
binding.ivCheck?.setOnClickListener {
itemBean.checked.set(!itemBean.checked.get())
FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED).tryEmit("check_changed")
binding.executePendingBindings()
}
binding.executePendingBindings()
}
}

View File

@@ -27,6 +27,22 @@ class UldListViewModel : BasePageViewModel() {
val uldSuffix = MutableLiveData("")
val uldNo = MutableLiveData("")
// ========== 手机版(5.5 寸手持端)筛选 ==========
// 后端确认查询入参与平板端保持一致(uld / status / uldSuffix),手机筛选弹层只放 状态 + 所属航司。
/** 手机版状态下拉:文案与卡片标签一致(可用=0 / 维修=1) */
val statusPhoneFilterList = MutableLiveData<List<KeyValue>>(
listOf(
KeyValue("全部", ""),
KeyValue("可用", "0"),
KeyValue("维修", "1"),
)
)
// ========== 手机版批量选择状态 ==========
val isAllChecked = MutableLiveData(false)
val selectedCount = MutableLiveData("0")
// 状态下拉列表
val statusList = MutableLiveData<List<KeyValue>>(
listOf(
@@ -65,12 +81,54 @@ class UldListViewModel : BasePageViewModel() {
)
}) {
onSuccess = {
pageModel.handleListBean(it.toBaseListBean())
pageModel.handleListBean(it.toBaseListBean()) { updateCheckAllStatus() }
count.value = it.total
}
}
}
// ========== 手机版:多选与批量删除 ==========
fun onItemCheckChanged() {
updateCheckAllStatus()
}
fun updateCheckAllStatus() {
val list = pageModel.rv?.commonAdapter()?.items?.filterIsInstance<ULDBean>() ?: return
isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() }
selectedCount.value = list.count { it.checked.get() }.toString()
}
fun toggleSelectAll() {
val list = pageModel.rv?.commonAdapter()?.items?.filterIsInstance<ULDBean>() ?: return
val shouldCheckAll = !(isAllChecked.value ?: false)
list.forEach { it.checked.set(shouldCheckAll) }
isAllChecked.value = shouldCheckAll
selectedCount.value = (if (shouldCheckAll) list.size else 0).toString()
pageModel.rv?.commonAdapter()?.notifyDataSetChanged()
}
fun getSelectedItems(): List<ULDBean> =
pageModel.rv?.commonAdapter()?.items?.filterIsInstance<ULDBean>()
?.filter { it.checked.get() } ?: emptyList()
/**
* 批量删除选中的 ULD(/eqm/uld/deleteUldBatch,请求体为 ULD 编号数组,一次调用)。
*/
fun deleteSelected() {
val ulds = getSelectedItems().map { it.uld }
if (ulds.isEmpty()) {
showToast("请选择要删除的ULD")
return
}
launchLoadingCollect({ NetApply.api.deleteUldBatch(ulds.toRequestBody()) }) {
onSuccess = {
showToast("已删除 ${ulds.size} 条")
refresh()
}
}
}
fun onUldScanClick() {
ScanModel.startScan(DevUtils.getTopActivity(), Constant.RequestCode.ULD)
}

View File

@@ -0,0 +1,153 @@
<?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"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.lukouguoji.module_base.ui.weight.search.layout.SearchLayoutType" />
<variable
name="viewModel"
type="com.lukouguoji.aerologic.page.gnj.move.stash.list.GnjMoveStashListViewModel" />
<!-- 平板不使用,仅为与手机变体保持 <variable> 一致(DataBinding 双变体强制约束) -->
<variable
name="activity"
type="com.lukouguoji.aerologic.page.gnj.move.stash.list.GnjMoveStashListActivity" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f2"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="10dp"
android:gravity="center_vertical">
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"请选择业务类型"}'
list="@{viewModel.businessTypeList}"
type="@{SearchLayoutType.SPINNER}"
value="@={viewModel.businessType}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"请输入运单号"}'
icon="@{@drawable/img_scan}"
setInputWaybill="@{true}"
setOnIconClickListener="@{()-> viewModel.waybillScanClick()}"
setRefreshCallBack="@{viewModel::refresh}"
setSearchListRefresh="@{viewModel::getWayBillList}"
type="@{SearchLayoutType.INPUT}"
value="@={viewModel.waybill}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"请输入承运人"}'
type="@{SearchLayoutType.INPUT}"
value="@={viewModel.carrier}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<ImageView
style="@style/iv_search_action"
android:onClick="@{()-> viewModel.refresh()}"
android:src="@drawable/img_search" />
</LinearLayout>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingTop="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:onClick="@{()->viewModel.checkAllClick()}"
android:text="全选" />
<ImageView
android:id="@+id/checkIcon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginLeft="5dp"
android:onClick="@{()->viewModel.checkAllClick()}"
android:src="@drawable/img_check_all" />
</androidx.appcompat.widget.LinearLayoutCompat>
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/srl"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_gnj_move_stash_list" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/color_bottom_layout"
android:gravity="center_vertical"
android:paddingHorizontal="15dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"合计:"+viewModel.count+"条,总件数:"+viewModel.number+",总重量:"+viewModel.weight+"KG"}'
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold"
tools:text="合计:3条,总件数:212,总重量:342KG" />
<TextView
style="@style/tv_bottom_btn"
android:onClick="@{()-> viewModel.moveStashClick()}"
android:text="移库" />
</LinearLayout>
</LinearLayout>
</layout>

View File

@@ -0,0 +1,231 @@
<?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>
<variable
name="viewModel"
type="com.lukouguoji.aerologic.page.log.detail.LogDetailViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f2"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="15dp">
<!-- 运单信息 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- 标题区 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@drawable/bg_white_radius_top_8"
android:gravity="center_vertical"
android:paddingHorizontal="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单信息"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<!-- 分割线(贯穿卡片宽度) -->
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#E7E7E7" />
<!-- 内容区 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_white_radius_bottom_8"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginEnd="15dp"
android:layout_marginVertical="12dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单号:"
android:textColor="#666666"
android:textSize="14sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.waybillNo}"
android:textColor="#333333"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单类型:"
android:textColor="#666666"
android:textSize="14sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.waybillType}"
android:textColor="#333333"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<!-- 流转状态 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:orientation="vertical">
<!-- 标题区 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@drawable/bg_white_radius_top_8"
android:gravity="center_vertical"
android:paddingHorizontal="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="流转状态"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<!-- 分割线 -->
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#E7E7E7" />
<!-- 内容区 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_white_radius_bottom_8"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_steps"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="23dp"
android:layout_marginEnd="15dp"
android:layout_marginVertical="12dp"
android:orientation="horizontal" />
</LinearLayout>
</LinearLayout>
<!-- 操作详情 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:orientation="vertical">
<!-- 标题区 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@drawable/bg_white_radius_top_8"
android:gravity="center_vertical"
android:paddingHorizontal="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="操作详情"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<!-- 分割线 -->
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#E7E7E7" />
<!-- 内容区 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_white_radius_bottom_8"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_timeline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:paddingStart="8dp"
android:nestedScrollingEnabled="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</layout>

View File

@@ -0,0 +1,214 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.lukouguoji.module_base.ui.weight.data.layout.DataLayoutType" />
<import type="com.lukouguoji.module_base.common.DetailsPageType" />
<variable
name="viewModel"
type="com.lukouguoji.aerologic.page.uld.edit.UldEditViewModel" />
<!-- 平板端不使用,但两个布局变体的 <variable> 必须一致(手机变体用它做详情态编辑入口与状态选择) -->
<variable
name="activity"
type="com.lukouguoji.aerologic.page.uld.edit.UldEditActivity" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f2"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="15dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_white_radius_8"
android:orientation="vertical"
android:padding="15dp">
<!-- Row 1: ULD编号 / 状态 / 自重 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType == DetailsPageType.Add}"
hint='@{"请输入ULD编号"}'
title='@{"ULD编号"}'
titleLength="@{7}"
type="@{DataLayoutType.INPUT}"
value='@={viewModel.uldBean.uld}' />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请选择状态"}'
list="@{viewModel.statusList}"
title='@{"状态"}'
titleLength="@{5}"
type="@{DataLayoutType.SPINNER}"
value='@={viewModel.uldBean.status}' />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入自重"}'
title='@{"自重"}'
titleLength="@{5}"
type="@{DataLayoutType.INPUT}"
value='@={viewModel.uldBean.uldWeight}' />
</LinearLayout>
<!-- Row 2: 最大装载容积 / 最大载重 / 所属航司 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入最大装载容积"}'
title='@{"最大装载容积"}'
titleLength="@{7}"
type="@{DataLayoutType.INPUT}"
value='@={viewModel.uldBean.maxVolume}' />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入最大载重"}'
title='@{"最大载重"}'
titleLength="@{5}"
type="@{DataLayoutType.INPUT}"
value='@={viewModel.uldBean.maxWeight}' />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请选择所属航司"}'
list="@{viewModel.carrierList}"
title='@{"所属航司"}'
titleLength="@{5}"
type="@{DataLayoutType.SPINNER}"
value='@={viewModel.uldBean.carrier}' />
</LinearLayout>
<!-- Row 3: 来源 / 入库时间 / 所在港 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请选择来源"}'
list="@{viewModel.sourceList}"
title='@{"来源"}'
titleLength="@{7}"
type="@{DataLayoutType.SPINNER}"
value='@={viewModel.uldBean.source}' />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请选择入库时间"}'
title='@{"入库时间"}'
titleLength="@{5}"
type="@{DataLayoutType.DATETIME}"
value='@={viewModel.uldBean.inStoreTime}' />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入所在港"}'
title='@{"所在港"}'
titleLength="@{5}"
type="@{DataLayoutType.INPUT}"
value='@={viewModel.uldBean.nowPort}' />
</LinearLayout>
<!-- 备注(全行,多行输入) -->
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入备注"}'
inputHeight="@{80}"
title='@{"备注"}'
titleLength="@{7}"
type="@{DataLayoutType.INPUT}"
value='@={viewModel.uldBean.remark}' />
</LinearLayout>
<!-- 底部操作按钮 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginTop="24dp"
android:gravity="center"
visible="@{viewModel.pageType != DetailsPageType.Details}">
<TextView
style="@style/tv_bottom_btn"
android:layout_width="120dp"
android:layout_marginEnd="20dp"
android:onClick="@{()-> viewModel.onCancelClick()}"
android:text="取消" />
<TextView
style="@style/tv_bottom_btn"
android:layout_width="120dp"
android:onClick="@{()-> viewModel.onSaveClick()}"
android:text="保存" />
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
</layout>

View File

@@ -0,0 +1,122 @@
<?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"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.lukouguoji.module_base.ui.weight.search.layout.SearchLayoutType" />
<variable
name="viewModel"
type="com.lukouguoji.aerologic.page.uld.list.UldListViewModel" />
<!-- 平板端不使用,但两个布局变体的 <variable> 必须一致(手机变体用它驱动筛选弹层) -->
<variable
name="activity"
type="com.lukouguoji.aerologic.page.uld.list.UldListActivity" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f2"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="10dp"
android:gravity="center_vertical">
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"选择状态"}'
list="@{viewModel.statusList}"
type="@{SearchLayoutType.SPINNER}"
value="@={viewModel.status}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.33" />
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"选择所属航司"}'
list="@{viewModel.carrierList}"
type="@{SearchLayoutType.SPINNER}"
value="@={viewModel.uldSuffix}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.33" />
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"请输入ULD编号"}'
icon="@{@drawable/img_scan}"
setOnIconClickListener="@{()-> viewModel.onUldScanClick()}"
type="@{SearchLayoutType.INPUT}"
value="@={viewModel.uldNo}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.33" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical|start"
android:orientation="horizontal"
android:paddingHorizontal="24dp">
<ImageView
android:layout_width="36dp"
android:layout_height="36dp"
android:onClick="@{()-> viewModel.refresh()}"
android:padding="2dp"
android:src="@drawable/img_search" />
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="16dp"
android:onClick="@{()-> viewModel.onAddClick()}"
android:src="@drawable/img_add" />
</LinearLayout>
</LinearLayout>
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/srl"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_uld_list" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/white"
android:gravity="center_vertical"
android:paddingHorizontal="15dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"合计:" + viewModel.count + "条"}'
android:textColor="@color/bottom_tool_tips_text_color"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</layout>

View File

@@ -0,0 +1,296 @@
<?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"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="bean"
type="com.lukouguoji.module_base.bean.MoveStashBean" />
<!-- 以下两个变量平板不使用,仅为与手机变体保持 <variable> 一致(DataBinding 双变体强制约束) -->
<variable
name="position"
type="Integer" />
<variable
name="activity"
type="com.lukouguoji.aerologic.page.gnj.move.stash.list.GnjMoveStashListActivity" />
</data>
<!-- 外层容器承载间距 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="5dp"
android:orientation="vertical">
<!-- 侧滑布局 -->
<com.mcxtzhang.swipemenulib.SwipeMenuLayout
android:id="@+id/swipe_menu"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- 主列表项容器 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_item"
android:orientation="horizontal"
android:padding="10dp">
<ImageView
android:id="@+id/iv_icon"
loadImage="@{bean.checked ? @drawable/img_plane_s : @drawable/img_plane}"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:src="@drawable/img_plane" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:orientation="vertical">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.1"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单号:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.wbNo}"
android:textColor="@color/colorPrimary"
tools:text="789165431" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="件数:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{bean.pc}' />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="重量:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.weight}" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="代理人:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{bean.agentCode}' />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.1"
android:gravity="center_vertical">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单类型:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{bean.awbType}' />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.1"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="航班:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.flight}" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="始发港:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.origin}" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="起始站:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.dep}" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="目的港:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.dest}" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.1"
android:gravity="center_vertical">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="品名:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.goods}" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</LinearLayout>
<!-- 右侧箭头 -->
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:src="@drawable/img_pda_right" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 侧滑菜单区域 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<!-- 编辑按钮 -->
<TextView
android:id="@+id/btn_edit"
style="@style/tv_item_action"
android:background="@color/colorPrimary"
android:text="编辑" />
</androidx.appcompat.widget.LinearLayoutCompat>
</com.mcxtzhang.swipemenulib.SwipeMenuLayout>
</LinearLayout>
</layout>

View File

@@ -0,0 +1,320 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="bean"
type="com.lukouguoji.module_base.bean.ULDBean" />
</data>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.mcxtzhang.swipemenulib.SwipeMenuLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="5dp"
android:background="@drawable/bg_item"
android:orientation="horizontal"
android:padding="10dp">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:src="@drawable/img_plane"
tools:src="@drawable/img_plane" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:orientation="vertical">
<!-- 第一行:ULD编号 | 状态 | 自重 | 所属航司 | 最大装载容积 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- ULD编号 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ULD编号:"
android:textSize="15sp"
completeSpace="@{5}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.uld}"
android:textColor="@color/colorPrimary"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 状态 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="状态:"
android:textSize="15sp"
completeSpace="@{3}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.statusName()}"
android:textColor='@{bean.status.equals("0") ? @color/text_green : @color/red}'
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 自重 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="自重:"
android:textSize="15sp"
completeSpace="@{4}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.uldWeight}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 所属航司 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="所属航司:"
android:textSize="15sp"
completeSpace="@{5}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.carrier}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 最大装载容积 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.2"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="最大装载容积:"
android:textSize="15sp"
completeSpace="@{7}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.maxVolume}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 第二行:最大载重 | 来源 | 所在港 | 位置 | 入库时间 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
<!-- 最大载重 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="最大载重:"
android:textSize="15sp"
completeSpace="@{5}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.maxWeight}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 来源 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="来源:"
android:textSize="15sp"
completeSpace="@{3}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.source}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 所在港 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="所在港:"
android:textSize="15sp"
completeSpace="@{4}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.nowPort}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 位置 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="位置:"
android:textSize="15sp"
completeSpace="@{5}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.nowPosition}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 入库时间 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.2"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="入库时间:"
android:textSize="15sp"
completeSpace="@{7}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.inStoreTime}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</LinearLayout>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:src="@drawable/img_pda_right" />
</androidx.appcompat.widget.LinearLayoutCompat>
</FrameLayout>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_modify"
style="@style/tv_item_action"
android:background="#8313ef"
android:text="修改" />
<TextView
android:id="@+id/tv_delete"
style="@style/tv_item_action"
android:background="@color/red"
android:text="删除" />
</androidx.appcompat.widget.LinearLayoutCompat>
</com.mcxtzhang.swipemenulib.SwipeMenuLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
</layout>

View File

@@ -0,0 +1,332 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
国内进港移库「运单详情」—— 5.5 寸手持端专属页面(无平板变体)
对应设计稿 11_进港移库 的「运单详情」页:
· 卡片一:蓝色表头(运单号 + 绿点 + 操作时间)+ 类型标签行(红「运单类型」+ 货物类型)
+ 品名大字 + 两列字段网格(件数/重量/特码/代理/出运路径/承运人)
· 卡片二:绿色表头「移库信息」+ 移库人 / 移库时间(仅已移库显示)
· 卡片三:橙色表头「异常照片」+ 三个虚线加号槽位(点击跳拍照上传页)
-->
<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="viewModel"
type="com.lukouguoji.aerologic.page.gnj.move.stash.detail.GnjMoveStashDetailViewModel" />
<variable
name="activity"
type="com.lukouguoji.aerologic.page.gnj.move.stash.detail.GnjMoveStashDetailActivity" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/phone_page_bg"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- ==================== 卡片一:运单基本信息 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card"
android:orientation="vertical">
<!-- 蓝色表头:运单号 + 绿点 + 操作时间 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card_header_blue"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp"
android:paddingVertical="12dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@{viewModel.dataBean.wbNo}"
android:textColor="@color/white"
android:textSize="17sp"
android:textStyle="bold" />
<View
android:layout_width="8dp"
android:layout_height="8dp"
android:layout_marginEnd="6dp"
android:background="@drawable/bg_phone_dot_green" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.opDate)}"
android:textColor="@color/white"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- 类型标签行:运单类型(红标签) + 货物类型 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="22dp"
android:background="@drawable/bg_phone_tag_red"
android:gravity="center"
android:paddingHorizontal="8dp"
android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.awbType)}"
android:textColor="@color/phone_tag_red_text"
android:textSize="12sp"
android:textStyle="bold" />
<View
android:layout_width="1dp"
android:layout_height="14dp"
android:layout_marginHorizontal="10dp"
android:background="@color/phone_divider" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.cargoType)}"
android:textColor="@color/phone_text_body"
android:textSize="14sp" />
</LinearLayout>
<!-- 品名(主字段大字) -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.goods)}"
android:textColor="@color/phone_text_strong"
android:textSize="22sp"
android:textStyle="bold" />
<!-- 第 1 行:件数 / 重量 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
title='@{"件数"}'
value="@{viewModel.dataBean.orDash(viewModel.dataBean.pc)}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_weight="1"
title='@{"重量"}'
value='@{viewModel.dataBean.orDash(viewModel.dataBean.weight) + " kg"}' />
</LinearLayout>
<!-- 第 2 行:特码 / 代理 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
title='@{"特码"}'
value="@{viewModel.dataBean.spCode}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_weight="1"
title='@{"代理"}'
value="@{viewModel.dataBean.agentDisplay}" />
</LinearLayout>
<!-- 第 3 行:出运路径 / 承运人 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
title='@{"出运路径"}'
value="@{viewModel.dataBean.range}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_weight="1"
title='@{"承运人"}'
value="@{viewModel.dataBean.by1}" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<!-- ==================== 卡片二:移库信息(仅已移库显示) ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/bg_phone_card"
android:orientation="vertical"
android:visibility="@{viewModel.dataBean.isMoved ? View.VISIBLE : View.GONE}">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card_header_green"
android:paddingHorizontal="16dp"
android:paddingVertical="10dp"
android:text="移库信息"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="16dp"
android:paddingVertical="12dp">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
title='@{"移库人"}'
value="@{viewModel.dataBean.opUserDisplay}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_weight="1"
title='@{"移库时间"}'
value="@{viewModel.dataBean.opDate}" />
</LinearLayout>
</LinearLayout>
<!-- ==================== 卡片三:异常照片 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/bg_phone_card"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card_header_orange"
android:paddingHorizontal="16dp"
android:paddingVertical="10dp"
android:text="异常照片"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold" />
<!-- 三个虚线加号槽位(等宽正方形由 weight + 固定高实现),点击进拍照上传页 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<TextView
android:layout_width="0dp"
android:layout_height="96dp"
android:layout_weight="1"
android:background="@drawable/bg_phone_photo_add"
android:gravity="center"
android:onClick="@{()-> activity.openPhoto()}"
android:text="+"
android:textColor="@color/phone_text_hint"
android:textSize="24sp" />
<TextView
android:layout_width="0dp"
android:layout_height="96dp"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:background="@drawable/bg_phone_photo_add"
android:gravity="center"
android:onClick="@{()-> activity.openPhoto()}"
android:text="+"
android:textColor="@color/phone_text_hint"
android:textSize="24sp" />
<TextView
android:layout_width="0dp"
android:layout_height="96dp"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:background="@drawable/bg_phone_photo_add"
android:gravity="center"
android:onClick="@{()-> activity.openPhoto()}"
android:text="+"
android:textColor="@color/phone_text_hint"
android:textSize="24sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
</layout>

View File

@@ -1,148 +1,147 @@
<?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"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.lukouguoji.module_base.ui.weight.search.layout.SearchLayoutType" />
<variable
name="viewModel"
type="com.lukouguoji.aerologic.page.gnj.move.stash.list.GnjMoveStashListViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f2"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="10dp"
android:gravity="center_vertical">
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"请选择业务类型"}'
list="@{viewModel.businessTypeList}"
type="@{SearchLayoutType.SPINNER}"
value="@={viewModel.businessType}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"请输入运单号"}'
icon="@{@drawable/img_scan}"
setInputWaybill="@{true}"
setOnIconClickListener="@{()-> viewModel.waybillScanClick()}"
setRefreshCallBack="@{viewModel::refresh}"
setSearchListRefresh="@{viewModel::getWayBillList}"
type="@{SearchLayoutType.INPUT}"
value="@={viewModel.waybill}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"请输入承运人"}'
type="@{SearchLayoutType.INPUT}"
value="@={viewModel.carrier}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<ImageView
style="@style/iv_search_action"
android:onClick="@{()-> viewModel.refresh()}"
android:src="@drawable/img_search" />
</LinearLayout>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingTop="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:onClick="@{()->viewModel.checkAllClick()}"
android:text="全选" />
<ImageView
android:id="@+id/checkIcon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginLeft="5dp"
android:onClick="@{()->viewModel.checkAllClick()}"
android:src="@drawable/img_check_all" />
</androidx.appcompat.widget.LinearLayoutCompat>
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/srl"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_gnj_move_stash_list" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/color_bottom_layout"
android:gravity="center_vertical"
android:paddingHorizontal="15dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"合计:"+viewModel.count+"条,总件数:"+viewModel.number+",总重量:"+viewModel.weight+"KG"}'
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold"
tools:text="合计:3条,总件数:212,总重量:342KG" />
<TextView
style="@style/tv_bottom_btn"
android:onClick="@{()-> viewModel.moveStashClick()}"
android:text="移库" />
</LinearLayout>
</LinearLayout>
</layout>
<?xml version="1.0" encoding="utf-8"?>
<!--
国内进港移库 —— 5.5 寸手持端布局(平板变体见 layout-sw600dp/ 同名文件)
对应设计稿 documents/5.5寸手持端设计文件/11_进港移库/进港移库.html:
· 顶部搜索框(运单号,含扫码)+ 筛选弹层(航班日期 / 航班号 / 特码 / 运单类型)
· 「待移库 / 已移库」Tab 绑定 viewModel.moveState("0"/"1"),
分别走 DomImpMove/search 与 DomImpMove/searchMoved 两个端点
· 已移库 Tab 下隐藏底部操作条(与设计稿一致)
· 卡片长按出「拍照」浮层(见 item_gnj_move_stash_list.xml)
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<import type="com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayoutType" />
<variable
name="viewModel"
type="com.lukouguoji.aerologic.page.gnj.move.stash.list.GnjMoveStashListViewModel" />
<variable
name="activity"
type="com.lukouguoji.aerologic.page.gnj.move.stash.list.GnjMoveStashListActivity" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/phone_page_bg">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<!-- ==================== 搜索行 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingTop="16dp"
android:paddingBottom="12dp">
<com.lukouguoji.module_base.ui.weight.phone.PhoneSearchBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"搜索运单号"}'
setOnFilterClickListener="@{(v)-> activity.toggleFilterPanel()}"
setOnScanClickListener="@{(v)-> viewModel.waybillScanClick()}"
setRefreshCallBack="@{viewModel::refresh}"
upperCase="@{true}"
value="@={viewModel.waybill}" />
</LinearLayout>
<!-- ==================== 待移库 / 已移库 Tab ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneStatusTab
android:layout_width="match_parent"
android:layout_height="wrap_content"
counts="@{viewModel.moveStateCounts}"
setOnTabChanged="@{viewModel::refresh}"
tabs="@{viewModel.moveStateTabs}"
value="@={viewModel.moveState}" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/phone_divider" />
<!-- ==================== 列表 ==================== -->
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/srl"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:overScrollMode="never"
android:paddingBottom="12dp"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="3"
tools:listitem="@layout/item_gnj_move_stash_list" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<!-- ==================== 底部操作条(已移库 Tab 下隐藏) ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneBottomBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
actionText='@{"移库"}'
allChecked="@{viewModel.isAllChecked}"
countText='@{"已选 " + viewModel.selectedCount + " 项"}'
setOnActionClick="@{(v)-> viewModel.moveStashClick()}"
setOnAllCheckClick="@{(v)-> viewModel.toggleSelectAll()}"
android:visibility="@{`1`.equals(viewModel.moveState) ? View.GONE : View.VISIBLE}" />
</LinearLayout>
<!-- ==================== 筛选弹层 ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFilterPanel
android:layout_width="match_parent"
android:layout_height="match_parent"
panelVisible="@{activity.filterPanelVisible}"
setOnConfirmClick="@{(v)-> activity.confirmFilter()}"
setOnDismissClick="@{(v)-> activity.toggleFilterPanel()}"
setOnResetClick="@{(v)-> activity.resetFilter()}"
title='@{"筛选条件"}'>
<!-- 承运人(入参 carrier,与平板搜索栏一致) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请输入承运人"}'
title='@{"承运人"}'
type="@{PhoneDataLayoutType.INPUT}"
value="@={viewModel.carrier}" />
<!-- 运单类型(入参 awbType,复用平板既有 businessType 字段与字典) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择运单类型"}'
list="@{viewModel.businessTypeList}"
title='@{"运单类型"}'
type="@{PhoneDataLayoutType.SPINNER}"
value="@={viewModel.businessType}" />
</com.lukouguoji.module_base.ui.weight.phone.PhoneFilterPanel>
</FrameLayout>
</layout>

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
国内进港移库「拍照上传」—— 5.5 寸手持端专属页面(无平板变体)
对应设计稿 11_进港移库/photo.html:
· 白卡「运单照片上传」+ 图片预览网格(复用公共 ImageSelectNewViewHolder,末位加号槽位)
· 底部两个按钮:拍照/上传(蓝) + 确认提交(绿)
提交走 DomImpMove/modify(pic/originalPic/picNumber 三字段规范)。
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.lukouguoji.aerologic.page.gnj.move.stash.photo.GnjMoveStashPhotoViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/phone_page_bg"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card"
android:orientation="vertical"
android:padding="16dp">
<!-- 标题:运单照片上传(副行展示运单号) -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单照片上传"
android:textColor="@color/phone_text_strong"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@{viewModel.wbNo}"
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="78133363573" />
<!-- 图片预览网格(末位加号槽位,长按出删除角标) -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:overScrollMode="never"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="3"
tools:itemCount="3" />
<!-- 底部按钮:拍照/上传(蓝) + 确认提交(绿) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="44dp"
android:layout_weight="1"
android:background="@drawable/bg_phone_btn_primary"
android:gravity="center"
android:onClick="@{()-> viewModel.pickClick()}"
android:text="拍照/上传"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="44dp"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:background="@drawable/bg_phone_btn_green"
android:gravity="center"
android:onClick="@{()-> viewModel.submitClick()}"
android:text="确认提交"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
</layout>

View File

@@ -1,6 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
操作日志详情(运单追踪)—— 手机版布局(5.5 寸手持端,最小宽度 < 600dp 时生效)
平板版为同名文件 layout-sw600dp/activity_log_detail.xml(横向步骤条 + 操作详情时间线),
两者是同一布局的资源变体,DataBinding 因此生成同一个 ActivityLogDetailBinding 类。
变体之间必须满足:
· DataBinding 变量完全一致:viewModel
· 保留 Activity 引用的控件 id:ll_steps / rv_timeline
手机版按设计稿「运单追踪」呈现:
· 顶卡:运单号 + 运单类型标签
· 流转状态:竖排时间线(LogDetailActivity 手机分支 buildVerticalSteps 动态填充 ll_steps)
· 平板的「操作详情」时间线列表在手机设计稿中不存在,rv_timeline 保留 id 但隐藏
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
@@ -12,7 +28,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f2"
android:background="@color/phone_page_bg"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
@@ -20,208 +36,99 @@
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
android:fillViewport="true"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="15dp">
android:padding="12dp">
<!-- 运单信息 -->
<!-- ==================== 运单卡片 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:background="@drawable/bg_phone_card"
android:orientation="vertical"
android:padding="16dp">
<!-- 标题区 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@drawable/bg_white_radius_top_8"
android:gravity="center_vertical"
android:paddingHorizontal="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单信息"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<!-- 分割线(贯穿卡片宽度) -->
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#E7E7E7" />
<!-- 内容区 -->
<!-- 运单号 + 运单类型标签 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_white_radius_bottom_8"
android:orientation="vertical">
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginEnd="15dp"
android:layout_marginVertical="12dp"
android:orientation="horizontal">
android:layout_weight="1"
android:text="@{viewModel.waybillNo}"
android:textColor="@color/phone_text_title"
android:textSize="20sp"
android:textStyle="bold"
tools:text="78133358743" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单号:"
android:textColor="#666666"
android:textSize="14sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.waybillNo}"
android:textColor="#333333"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单类型:"
android:textColor="#666666"
android:textSize="14sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.waybillType}"
android:textColor="#333333"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="22dp"
android:layout_marginStart="8dp"
android:background="@drawable/bg_phone_tag_indigo"
android:gravity="center"
android:paddingHorizontal="10dp"
android:text="@{viewModel.waybillType}"
android:textColor="@color/phone_tag_indigo_text"
android:textSize="12sp"
tools:text="国际出港" />
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginTop="14dp"
android:layout_marginBottom="14dp"
android:background="@color/phone_divider" />
<!-- 流转状态标题 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="流转状态"
android:textColor="@color/phone_text_title"
android:textSize="15sp"
android:textStyle="bold" />
<!-- 竖排时间线(Activity 手机分支动态填充) -->
<LinearLayout
android:id="@+id/ll_steps"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="14dp"
android:orientation="vertical" />
<!-- 平板的操作详情时间线,手机设计稿无此区块,保留 id 但隐藏 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_timeline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>
<!-- 流转状态 -->
<LinearLayout
android:layout_width="match_parent"
<!-- 触底提示 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:orientation="vertical">
<!-- 标题区 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@drawable/bg_white_radius_top_8"
android:gravity="center_vertical"
android:paddingHorizontal="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="流转状态"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<!-- 分割线 -->
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#E7E7E7" />
<!-- 内容区 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_white_radius_bottom_8"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_steps"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="23dp"
android:layout_marginEnd="15dp"
android:layout_marginVertical="12dp"
android:orientation="horizontal" />
</LinearLayout>
</LinearLayout>
<!-- 操作详情 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:orientation="vertical">
<!-- 标题区 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@drawable/bg_white_radius_top_8"
android:gravity="center_vertical"
android:paddingHorizontal="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="操作详情"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<!-- 分割线 -->
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#E7E7E7" />
<!-- 内容区 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_white_radius_bottom_8"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_timeline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:paddingStart="8dp"
android:nestedScrollingEnabled="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>
</LinearLayout>
android:layout_gravity="center_horizontal"
android:layout_marginTop="24dp"
android:layout_marginBottom="16dp"
android:letterSpacing="0.3"
android:text="查询信息已触底"
android:textColor="@color/phone_text_hint"
android:textSize="12sp" />
</LinearLayout>

View File

@@ -1,210 +1,260 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<!--
ULD新增 / 修改 / 详情 —— 手机版布局(5.5 寸手持端,最小宽度 < 600dp 时生效)
平板版为同名文件 layout-sw600dp/activity_uld_edit.xml(PadDataLayoutNew 三列表单),
两者是同一布局的资源变体,DataBinding 生成同一个 ActivityUldEditBinding 类。
变体之间必须满足:
· DataBinding 变量完全一致:viewModel / activity
→ UldEditViewModel 的加载/保存逻辑全部复用,平板端行为不受影响
一套布局覆盖设计稿三个页面(标题由 Activity 按 pageType 设置):
· ULD新增(Add) :可编辑 + 底部保存;所在港默认 HFE、必填星(编号/自重/入库时间)
· ULD修改(Modify):编号只读,其余可编辑 + 底部保存
· ULD详情(Details):全只读右对齐 + 顶栏右侧铅笔进入修改 + 额外展示最大装载容积/最大载重
字段与平板端一致:来源 source(空运/陆运)、入库时间 inStoreTime、所在港 nowPort;
状态维持两态(0 可用 / 1 维修,后端不新增「占用」)。
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="com.lukouguoji.module_base.ui.weight.data.layout.DataLayoutType" />
<import type="android.view.View" />
<import type="com.lukouguoji.module_base.common.DetailsPageType" />
<import type="com.lukouguoji.module_base.ui.weight.phone.PhoneFormRowType" />
<variable
name="viewModel"
type="com.lukouguoji.aerologic.page.uld.edit.UldEditViewModel" />
<variable
name="activity"
type="com.lukouguoji.aerologic.page.uld.edit.UldEditActivity" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f2"
android:background="@color/phone_page_bg"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<!-- 标题栏 + 详情态右侧铅笔(编辑入口) -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/title_tool_bar" />
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="end"
android:onClick="@{()-> activity.onEditClick()}"
android:padding="14dp"
android:src="@drawable/ic_phone_edit"
android:visibility="@{viewModel.pageType == DetailsPageType.Details ? View.VISIBLE : View.GONE}" />
</FrameLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true">
android:fillViewport="true"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="15dp">
android:padding="16dp">
<!-- ==================== 表单卡片 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_white_radius_8"
android:background="@drawable/bg_phone_card"
android:orientation="vertical"
android:padding="15dp">
android:paddingHorizontal="16dp">
<!-- Row 1: ULD编号 / 状态 / 自重 -->
<!-- ULD编号:新增可输,修改/详情只读 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
enable="@{viewModel.pageType == DetailsPageType.Add}"
hint='@{"请输入ULD编号"}'
required="@{viewModel.pageType == DetailsPageType.Add}"
title='@{"ULD编号"}'
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.INPUT}"
value="@={viewModel.uldBean.uld}" />
<!-- 状态:彩色标签 + 底部选择面板(详情态右对齐、无箭头) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="54dp"
android:onClick="@{()-> activity.onStatusRowClick()}"
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
<TextView
android:layout_width="110dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType == DetailsPageType.Add}"
hint='@{"请输入ULD编号"}'
title='@{"ULD编号"}'
titleLength="@{7}"
type="@{DataLayoutType.INPUT}"
value='@={viewModel.uldBean.uld}' />
android:text="状态"
android:textColor="@color/phone_text_label"
android:textSize="15sp" />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
<!-- 详情态用这个占位把标签推到右侧 -->
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="1dp"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请选择状态"}'
list="@{viewModel.statusList}"
title='@{"状态"}'
titleLength="@{5}"
type="@{DataLayoutType.SPINNER}"
value='@={viewModel.uldBean.status}' />
android:visibility="@{viewModel.pageType == DetailsPageType.Details ? View.VISIBLE : View.GONE}" />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
<TextView
android:layout_width="wrap_content"
android:layout_height="22dp"
android:background="@{viewModel.uldBean.status.empty ? null : (viewModel.uldBean.isStatusAvailable ? @drawable/bg_phone_tag_green : @drawable/bg_phone_tag_red_light)}"
android:gravity="center"
android:paddingHorizontal="8dp"
android:text='@{viewModel.uldBean.status.empty ? "请选择状态" : viewModel.uldBean.statusPhoneName}'
android:textColor="@{viewModel.uldBean.status.empty ? @color/phone_text_hint : (viewModel.uldBean.isStatusAvailable ? @color/phone_tag_green_text : @color/phone_danger_text)}"
android:textSize="12sp" />
<!-- 编辑态右箭头 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入自重"}'
title='@{"自重"}'
titleLength="@{5}"
type="@{DataLayoutType.INPUT}"
value='@={viewModel.uldBean.uldWeight}' />
android:gravity="end|center_vertical"
android:orientation="horizontal"
android:visibility="@{viewModel.pageType == DetailsPageType.Details ? View.GONE : View.VISIBLE}">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_phone_chevron_right" />
</LinearLayout>
</LinearLayout>
<!-- Row 2: 最大装载容积 / 最大载重 / 所属航司 -->
<LinearLayout
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/phone_divider" />
<!-- 所属航司 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请选择所属航司"}'
list="@{viewModel.carrierList}"
title='@{"所属航司"}'
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.SELECT}"
value="@={viewModel.uldBean.carrier}" />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入最大装载容积"}'
title='@{"最大装载容积"}'
titleLength="@{7}"
type="@{DataLayoutType.INPUT}"
value='@={viewModel.uldBean.maxVolume}' />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入最大载重"}'
title='@{"最大载重"}'
titleLength="@{5}"
type="@{DataLayoutType.INPUT}"
value='@={viewModel.uldBean.maxWeight}' />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请选择所属航司"}'
list="@{viewModel.carrierList}"
title='@{"所属航司"}'
titleLength="@{5}"
type="@{DataLayoutType.SPINNER}"
value='@={viewModel.uldBean.carrier}' />
</LinearLayout>
<!-- Row 3: 来源 / 入库时间 / 所在港 -->
<LinearLayout
<!-- 自重(kg) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入自重"}'
numeric="@{true}"
title='@{"自重(kg)"}'
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.INPUT}"
value="@={viewModel.uldBean.uldWeight}" />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请选择来源"}'
list="@{viewModel.sourceList}"
title='@{"来源"}'
titleLength="@{7}"
type="@{DataLayoutType.SPINNER}"
value='@={viewModel.uldBean.source}' />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请选择入库时间"}'
title='@{"入库时间"}'
titleLength="@{5}"
type="@{DataLayoutType.DATETIME}"
value='@={viewModel.uldBean.inStoreTime}' />
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入所在港"}'
title='@{"所在港"}'
titleLength="@{5}"
type="@{DataLayoutType.INPUT}"
value='@={viewModel.uldBean.nowPort}' />
</LinearLayout>
<!-- 备注(全行,多行输入) -->
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
<!-- 最大装载容积 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入最大装载容积"}'
numeric="@{true}"
title='@{"最大装载容积(m³)"}'
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.INPUT}"
value="@={viewModel.uldBean.maxVolume}" />
<!-- 最大载重 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入最大载重"}'
numeric="@{true}"
title='@{"最大载重(kg)"}'
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.INPUT}"
value="@={viewModel.uldBean.maxWeight}" />
<!-- 所在港(nowPort,新增默认 HFE) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入所在港"}'
title='@{"所在港"}'
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.INPUT}"
value="@={viewModel.uldBean.nowPort}" />
<!-- 来源(source:空运/陆运,设计稿顺序位于所在港之后) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请选择来源"}'
list="@{viewModel.sourceList}"
title='@{"来源"}'
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.SELECT}"
value="@={viewModel.uldBean.source}" />
<!-- 入库时间(inStoreTime,与平板端一致) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入入库时间"}'
title='@{"入库时间"}'
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.DATE}"
value="@={viewModel.uldBean.inStoreTime}" />
<!-- 备注 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入备注"}'
inputHeight="@{80}"
title='@{"备注"}'
titleLength="@{7}"
type="@{DataLayoutType.INPUT}"
value='@={viewModel.uldBean.remark}' />
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.INPUT}"
value="@={viewModel.uldBean.remark}" />
</LinearLayout>
<!-- 底部操作按钮 -->
<LinearLayout
<!-- ==================== 保存按钮(详情态隐藏) ==================== -->
<TextView
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_height="48dp"
android:layout_marginTop="24dp"
android:background="@drawable/bg_phone_btn_primary"
android:gravity="center"
visible="@{viewModel.pageType != DetailsPageType.Details}">
<TextView
style="@style/tv_bottom_btn"
android:layout_width="120dp"
android:layout_marginEnd="20dp"
android:onClick="@{()-> viewModel.onCancelClick()}"
android:text="取消" />
<TextView
style="@style/tv_bottom_btn"
android:layout_width="120dp"
android:onClick="@{()-> viewModel.onSaveClick()}"
android:text="保存" />
</LinearLayout>
android:onClick="@{()-> viewModel.onSaveClick()}"
android:text="保存"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
android:visibility="@{viewModel.pageType == DetailsPageType.Details ? View.GONE : View.VISIBLE}" />
</LinearLayout>
</ScrollView>
</LinearLayout>
</layout>

View File

@@ -1,118 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
ULD管理 —— 手机版布局(5.5 寸手持端,最小宽度 < 600dp 时生效)
平板版为同名文件 layout-sw600dp/activity_uld_list.xml,两者是同一布局的资源变体,
DataBinding 因此生成同一个 ActivityUldListBinding 类。
变体之间必须满足:
· DataBinding 变量完全一致:viewModel / activity
· 保留 Activity 中引用的控件 id:srl / rv
→ UldListViewModel 的业务逻辑与接口调用全部复用,平板端行为不受影响
交互差异(均复用既有 ViewModel 字段与接口):
· 平板 3 个横排搜索条 → 手机顶部搜索框(ULD 编号)+ 底部筛选弹层
(入库时间 / 进港航班号 / 所属航司 / 来源;前两项与来源的筛选入参后端暂不支持,
已登记 documents/后端接口对接问题清单.xlsx,后端支持后自动生效)
· 平板右上「新增」按钮 → 手机右下角浮动 + 按钮
· 平板侧滑单条删除 → 手机底部操作条(全选 + 已选统计 + 批量删除)
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.lukouguoji.module_base.ui.weight.search.layout.SearchLayoutType" />
<import type="com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayoutType" />
<variable
name="viewModel"
type="com.lukouguoji.aerologic.page.uld.list.UldListViewModel" />
<variable
name="activity"
type="com.lukouguoji.aerologic.page.uld.list.UldListActivity" />
</data>
<LinearLayout
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f2"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
android:background="@color/phone_page_bg">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="10dp"
android:gravity="center_vertical">
android:layout_height="match_parent"
android:orientation="vertical">
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"选择状态"}'
list="@{viewModel.statusList}"
type="@{SearchLayoutType.SPINNER}"
value="@={viewModel.status}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.33" />
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"选择所属航司"}'
list="@{viewModel.carrierList}"
type="@{SearchLayoutType.SPINNER}"
value="@={viewModel.uldSuffix}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.33" />
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
hint='@{"请输入ULD编号"}'
icon="@{@drawable/img_scan}"
setOnIconClickListener="@{()-> viewModel.onUldScanClick()}"
type="@{SearchLayoutType.INPUT}"
value="@={viewModel.uldNo}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.33" />
<include layout="@layout/title_tool_bar" />
<!-- ==================== 搜索行 ==================== -->
<LinearLayout
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical|start"
android:orientation="horizontal"
android:paddingHorizontal="24dp">
android:background="@color/white"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingTop="16dp"
android:paddingBottom="12dp">
<ImageView
android:layout_width="36dp"
android:layout_height="36dp"
android:onClick="@{()-> viewModel.refresh()}"
android:padding="2dp"
android:src="@drawable/img_search" />
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="16dp"
android:onClick="@{()-> viewModel.onAddClick()}"
android:src="@drawable/img_add" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneSearchBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"搜索ULD编号"}'
setOnFilterClickListener="@{(v)-> activity.toggleFilterPanel()}"
setOnScanClickListener="@{(v)-> viewModel.onUldScanClick()}"
setRefreshCallBack="@{viewModel::refresh}"
upperCase="@{true}"
value="@={viewModel.uldNo}" />
</LinearLayout>
</LinearLayout>
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/srl"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
<!-- ==================== 列表 ==================== -->
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/srl"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_uld_list" />
android:layout_height="0dp"
android:layout_weight="1">
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:overScrollMode="never"
android:paddingBottom="80dp"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="4"
tools:listitem="@layout/item_uld_list" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/white"
android:gravity="center_vertical"
android:paddingHorizontal="15dp">
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"合计:" + viewModel.count + "条"}'
android:textColor="@color/bottom_tool_tips_text_color"
android:textSize="18sp"
android:textStyle="bold" />
<!-- ==================== 底部操作条:全选 + 已选统计 + 批量删除 ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneBottomBar
actionDanger="@{true}"
actionText='@{"删除"}'
allChecked="@{viewModel.isAllChecked}"
countText='@{"已选 " + viewModel.selectedCount + " / " + viewModel.count + " 项"}'
setOnActionClick="@{(v)-> activity.showDeleteConfirmDialog()}"
setOnAllCheckClick="@{(v)-> viewModel.toggleSelectAll()}"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<!-- ==================== 右下角浮动新增按钮 ==================== -->
<TextView
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_gravity="bottom|end"
android:layout_marginEnd="20dp"
android:layout_marginBottom="92dp"
android:background="@drawable/bg_phone_fab"
android:elevation="6dp"
android:gravity="center"
android:includeFontPadding="false"
android:onClick="@{()-> viewModel.onAddClick()}"
android:text="+"
android:textColor="@color/white"
android:textSize="32sp" />
<!-- ==================== 筛选弹层 ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFilterPanel
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="8dp"
panelVisible="@{activity.filterPanelVisible}"
setOnConfirmClick="@{(v)-> activity.confirmFilter()}"
setOnDismissClick="@{(v)-> activity.toggleFilterPanel()}"
setOnResetClick="@{(v)-> activity.resetFilter()}"
title='@{"筛选条件"}'>
<!-- 状态(后端入参 status,与平板端查询参数一致) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择状态"}'
list="@{viewModel.statusPhoneFilterList}"
title='@{"状态"}'
type="@{PhoneDataLayoutType.SPINNER}"
value="@={viewModel.status}" />
<!-- 所属航司(后端入参 uldSuffix,真实生效) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择所属航司"}'
list="@{viewModel.carrierList}"
title='@{"所属航司"}'
type="@{PhoneDataLayoutType.SPINNER}"
value="@={viewModel.uldSuffix}" />
</com.lukouguoji.module_base.ui.weight.phone.PhoneFilterPanel>
</FrameLayout>
</layout>

View File

@@ -1,287 +1,227 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
国内进港移库 —— 列表项 5.5 寸手持端布局(平板变体见 layout-sw600dp/ 同名文件)
一套布局覆盖设计稿两种卡片形态,按 bean.isMoved 切换(载入时按端点打标):
· 待移库:圆形勾选框 + 蓝色运单号 + 橙色「待移库」标签
· 已移库:无勾选框 + 深色运单号 + 绿色对勾「已移库」
长按卡片出「拍照」浮层(跳拍照上传页),点浮层空白处收起。
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="bean"
type="com.lukouguoji.module_base.bean.MoveStashBean" />
<variable
name="position"
type="Integer" />
<variable
name="activity"
type="com.lukouguoji.aerologic.page.gnj.move.stash.list.GnjMoveStashListActivity" />
</data>
<!-- 外层容器承载间距 -->
<LinearLayout
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="5dp"
android:orientation="vertical">
android:layout_marginHorizontal="12dp"
android:layout_marginTop="12dp">
<!-- 侧滑布局 -->
<com.mcxtzhang.swipemenulib.SwipeMenuLayout
android:id="@+id/swipe_menu"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card"
android:onLongClick="@{()-> activity.showCardActionPhone(bean)}"
android:orientation="vertical"
android:padding="16dp">
<!-- 主列表项容器 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll"
<!-- ==================== 卡片头部:勾选框 + 运单号 + 状态 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_item"
android:orientation="horizontal"
android:padding="10dp">
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- 圆形勾选框(已移库的记录不可勾选,隐藏) -->
<ImageView
android:id="@+id/iv_icon"
loadImage="@{bean.checked ? @drawable/img_plane_s : @drawable/img_plane}"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:src="@drawable/img_plane" />
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginEnd="8dp"
android:src="@drawable/ic_phone_check_round_unchecked"
android:visibility="@{bean.isMoved ? View.GONE : View.VISIBLE}"
loadImage="@{bean.checked.get() ? @drawable/ic_phone_check_round_checked : @drawable/ic_phone_check_round_unchecked}" />
<LinearLayout
<!-- 运单号 -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:orientation="vertical">
android:text="@{bean.wbNo}"
android:textColor="@{bean.isMoved ? @color/phone_text_title : @color/phone_primary}"
android:textSize="15sp"
android:textStyle="bold" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- 待移库:橙色状态标签 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginStart="8dp"
android:background="@drawable/bg_phone_tag_orange"
android:gravity="center"
android:paddingHorizontal="8dp"
android:text="待移库"
android:textColor="@color/phone_tag_orange_text"
android:textSize="11sp"
android:visibility="@{bean.isMoved ? View.GONE : View.VISIBLE}" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.1"
android:gravity="center_vertical">
<!-- 已移库:对勾 + 状态文字 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="@{bean.isMoved ? View.VISIBLE : View.GONE}">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单号:" />
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_phone_check_circle" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.wbNo}"
android:textColor="@color/colorPrimary"
tools:text="789165431" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="件数:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{bean.pc}' />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="重量:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.weight}" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="代理人:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{bean.agentCode}' />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.1"
android:gravity="center_vertical">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单类型:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{bean.awbType}' />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.1"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="航班:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.flight}" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="始发港:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.origin}" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="起始站:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.dep}" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
completeSpace="@{4}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="目的港:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.dest}" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.1"
android:gravity="center_vertical">
<TextView
completeSpace="@{5}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="品名:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.goods}" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
android:layout_marginStart="4dp"
android:text="已移库"
android:textColor="@color/phone_text_title"
android:textSize="13sp" />
</LinearLayout>
<!-- 右侧箭头 -->
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:src="@drawable/img_pda_right" />
</LinearLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 侧滑菜单区域 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="match_parent"
<!-- ==================== 航班信息行 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- 编辑按钮 -->
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_airplane" />
<TextView
android:id="@+id/btn_edit"
style="@style/tv_item_action"
android:background="@color/colorPrimary"
android:text="编辑" />
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_weight="1"
android:text='@{"航班信息:" + bean.orDash(bean.flight)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="航班信息:20260709/MU2311" />
</androidx.appcompat.widget.LinearLayoutCompat>
</LinearLayout>
</com.mcxtzhang.swipemenulib.SwipeMenuLayout>
<!-- ==================== 统计框:特码 / 件数 / 重量 ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneStatBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
label1='@{"特码"}'
label2='@{"件数"}'
label3='@{"重量"}'
value1="@{bean.orDash(bean.spCode)}"
value2='@{bean.orDash(bean.pc) + "件"}'
value3='@{bean.orDash(bean.weight) + "kg"}' />
</LinearLayout>
<!-- ==================== 出运路径 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_location" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_weight="1"
android:text='@{"出运路径:" + bean.orDash(bean.range)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp" />
</LinearLayout>
<!-- ==================== 查看详情 ==================== -->
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginTop="16dp"
android:background="@color/phone_stat_bg" />
<LinearLayout
android:id="@+id/ll_detail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|end"
android:orientation="horizontal"
android:paddingTop="12dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="查看详情"
android:textColor="@color/phone_primary"
android:textSize="14sp" />
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_phone_chevron_right" />
</LinearLayout>
</LinearLayout>
<!-- ==================== 长按操作浮层:拍照 ==================== -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#66000000"
android:clickable="true"
android:onClick="@{()-> activity.hideCardActionPhone(bean)}"
android:visibility="@{bean.actionMenuVisible ? View.VISIBLE : View.GONE}">
<TextView
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_gravity="center"
android:background="@drawable/bg_phone_fab_purple"
android:gravity="center"
android:onClick="@{()-> activity.openPhoto(bean)}"
android:text="拍照"
android:textColor="@color/white"
android:textSize="12sp"
android:textStyle="bold" />
</FrameLayout>
</FrameLayout>
</layout>

View File

@@ -1,320 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
ULD管理 —— 列表项手机版布局(5.5 寸手持端,最小宽度 < 600dp 时生效)
平板版为同名文件 layout-sw600dp/item_uld_list.xml(SwipeMenuLayout 侧滑修改/删除),
两者是同一布局的资源变体,DataBinding 生成同一个 ItemUldListBinding 类。
变体之间必须满足:
· DataBinding 变量完全一致:bean
· 保留 ViewHolder / ViewModel 引用的 id:ll_content(点卡片进详情,复用平板 onItemClick 链路)
· 平板独有 id(tv_modify / tv_delete / iv_icon)与手机独有 id(iv_check)
在 Binding 基类中自动为 @Nullable,ViewHolder 判空使用
状态标签:可用=浅绿 / 维修=浅红(后端枚举维持两态 0/1,不含「占用」),见 ULDBean.statusPhoneName。
「来源」字段后端暂无(恒空显示 "-"),已登记 documents/后端接口对接问题清单.xlsx。
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="bean"
type="com.lukouguoji.module_base.bean.ULDBean" />
</data>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:layout_marginHorizontal="12dp"
android:layout_marginTop="12dp"
android:background="@drawable/bg_phone_card"
android:orientation="vertical"
android:padding="16dp">
<com.mcxtzhang.swipemenulib.SwipeMenuLayout
<!-- ==================== 头行:勾选框 + ULD编号 + 状态标签 + 箭头 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_check"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginEnd="8dp"
android:src="@drawable/ic_phone_check_round_unchecked"
loadImage="@{bean.checked.get() ? @drawable/ic_phone_check_round_checked : @drawable/ic_phone_check_round_unchecked}" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="5dp"
android:background="@drawable/bg_item"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@{bean.uld}"
android:textColor="@color/phone_text_title"
android:textSize="15sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/iv_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:src="@drawable/img_plane"
tools:src="@drawable/img_plane" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:orientation="vertical">
<!-- 第一行:ULD编号 | 状态 | 自重 | 所属航司 | 最大装载容积 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- ULD编号 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ULD编号:"
android:textSize="15sp"
completeSpace="@{5}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.uld}"
android:textColor="@color/colorPrimary"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 状态 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="状态:"
android:textSize="15sp"
completeSpace="@{3}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.statusName()}"
android:textColor='@{bean.status.equals("0") ? @color/text_green : @color/red}'
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 自重 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="自重:"
android:textSize="15sp"
completeSpace="@{4}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.uldWeight}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 所属航司 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="所属航司:"
android:textSize="15sp"
completeSpace="@{5}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.carrier}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 最大装载容积 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.2"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="最大装载容积:"
android:textSize="15sp"
completeSpace="@{7}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.maxVolume}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 第二行:最大载重 | 来源 | 所在港 | 位置 | 入库时间 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
<!-- 最大载重 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="最大载重:"
android:textSize="15sp"
completeSpace="@{5}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.maxWeight}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 来源 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="来源:"
android:textSize="15sp"
completeSpace="@{3}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.source}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 所在港 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="所在港:"
android:textSize="15sp"
completeSpace="@{4}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.nowPort}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 位置 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="位置:"
android:textSize="15sp"
completeSpace="@{5}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.nowPosition}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 入库时间 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.2"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="入库时间:"
android:textSize="15sp"
completeSpace="@{7}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.inStoreTime}"
android:textSize="15sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</LinearLayout>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:src="@drawable/img_pda_right" />
</androidx.appcompat.widget.LinearLayoutCompat>
</FrameLayout>
<androidx.appcompat.widget.LinearLayoutCompat
<!-- 状态标签:可用(绿) / 维修(红,浅红底红字) -->
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent">
android:layout_height="20dp"
android:layout_marginStart="8dp"
android:background="@{bean.isStatusAvailable ? @drawable/bg_phone_tag_green : @drawable/bg_phone_tag_red_light}"
android:gravity="center"
android:paddingHorizontal="8dp"
android:text="@{bean.statusPhoneName}"
android:textColor="@{bean.isStatusAvailable ? @color/phone_tag_green_text : @color/phone_danger_text}"
android:textSize="11sp" />
<TextView
android:id="@+id/tv_modify"
style="@style/tv_item_action"
android:background="#8313ef"
android:text="修改" />
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="6dp"
android:src="@drawable/ic_phone_chevron_right" />
<TextView
android:id="@+id/tv_delete"
style="@style/tv_item_action"
android:background="@color/red"
android:text="删除" />
</LinearLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- ==================== 第二行:所属航司 / 来源 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:gravity="center_vertical"
android:orientation="horizontal">
</com.mcxtzhang.swipemenulib.SwipeMenuLayout>
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_airplane" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_weight="1"
android:text='@{"所属航司:" + (bean.carrier.empty ? "-" : bean.carrier)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp" />
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_location" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_weight="1"
android:text='@{"来源:" + (bean.source.empty ? "-" : bean.source)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp" />
</LinearLayout>
<!-- ==================== 所在港 / 位置(与平板列表一致) ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_weight="1"
android:text='@{"所在港:" + (bean.nowPort.empty ? "-" : bean.nowPort)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_weight="1"
android:text='@{"位置:" + (bean.nowPosition.empty ? "-" : bean.nowPosition)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp" />
</LinearLayout>
<!-- ==================== 第三行:入库时间 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_calendar" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_weight="1"
android:text='@{"入库时间:" + (bean.inStoreTime.empty ? "-" : bean.inStoreTime)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp" />
</LinearLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
</layout>