fix: 11模块设计稿全量走查修正——时间线状态pill/手机短标题/ULD字段顺序/计重卡片图标

设计稿逐态渲染对照走查(01~11 全模块)后的修正:
- 运单追踪竖排时间线为已发生节点补状态pill(绿底展示该环节日志content,超长省略)
- 11 页手机端标题按设计稿改短标题(DeviceUtil.isPhone 分支,平板长标题零变化):
  出库交接/出港待计重/计重记录/计重明细/开始计重/出港运抵/出港移库/出港查询/
  出港货物/进港查询/进港货物
- ULD 编辑表单「来源」移至「所在港」之后(设计稿顺序)
- 出港计重列表卡片与计重记录卡片补字段小图标(airplane/location/person/tag)

接口缺口台账复核:#31 进港移库整模块缺失成立(api-doc 全模块清单+报价单双重印证);
#19 修正定性——IntExpArrive/declare 入参已含收发货人全套字段,改登记为待确认提交口径;
#10 成立(单条 deleteUld 在、批量无)。

双端抽验:手机短标题三页生效(出港待计重/出库交接/进港货物),平板保持长标题,零崩溃。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-31 23:12:14 +08:00
parent a33776d959
commit eb0655d3fc
17 changed files with 1124 additions and 1009 deletions

View File

@@ -33,6 +33,14 @@
表头)、`bg_phone_photo_add`(虚线加号槽位)、色值 `phone_amber`
### 修复 (Fixed)
- 【11 模块全量设计稿走查】修正 4 类差异2026-07-313 个并行审计 + 逐态渲染比对):
① 运单追踪手机竖排时间线补齐已发生节点的状态 pill绿底标签展示该环节日志 content
如「放行状态01」超长省略设计稿 06/08 运单追踪均有此元素);
② 11 个页面手机端标题对齐设计稿短标题(出库交接/出港待计重/计重记录/计重明细/开始计重/
出港运抵/出港移库/出港查询/出港货物/进港查询/进港货物),平板保持原长标题零变化;
③ ULD 编辑表单「来源」字段移至「所在港」之后(设计稿顺序);
④ 出港计重列表卡片(日期/航程/代理/特码)与计重记录卡片(代理)补齐字段小图标
(复用 ic_phone_airplane/location/person/tag与其余模块卡片风格统一
- 出港查询/进港查询卡片「代理人」空值兜底失效:转换器把 JSON null 归一成空串DataBinding
`??` 只判 null 不判空串导致 agentCode 回退永不生效;改用 Bean 计算属性 `agentDisplay`
isNullOrEmpty 双兜底),已同步修正 06 出港查询(`item_gjc_query.xml`

View File

@@ -91,7 +91,9 @@ class LogDetailActivity : BaseBindingActivity<ActivityLogDetailBinding, LogDetai
val step = steps[i]
val isActive = step.code in activeCodes
val isLast = i == steps.size - 1
val time = logs.lastOrNull { it.status == step.code }?.opDate ?: ""
val stepLog = logs.lastOrNull { it.status == step.code }
val time = stepLog?.opDate ?: ""
val statusContent = stepLog?.content ?: ""
val row = LinearLayout(this).apply {
orientation = LinearLayout.HORIZONTAL
@@ -141,12 +143,41 @@ class LogDetailActivity : BaseBindingActivity<ActivityLogDetailBinding, LogDetai
}
setPadding(0, 0, 0, if (isLast) 0 else dp(24))
}
content.addView(TextView(this).apply {
// 名称行:步骤名(左)+ 已发生节点的状态 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

View File

@@ -160,17 +160,6 @@
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.SELECT}"
value="@={viewModel.uldBean.carrier}" />
<!-- 来源(后端字段暂不支持,已登记清单;提交后端忽略) -->
<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.sourceEditList}"
title='@{"来源"}'
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.SELECT}"
value="@={viewModel.uldBean.source}" />
<!-- 自重(kg) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
@@ -221,6 +210,17 @@
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.INPUT}"
value="@={viewModel.uldBean.airport}" />
<!-- 来源(设计稿顺序位于所在港之后;后端字段暂不支持,已登记清单,提交后端忽略) -->
<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.sourceEditList}"
title='@{"来源"}'
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.SELECT}"
value="@={viewModel.uldBean.source}" />
<!-- 入库时间(绑 checkInDate筛选/格式语义待后端确认,已登记清单) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"

View File

@@ -32,7 +32,7 @@ class GjcQueryActivity :
override fun viewModelClass() = GjcQueryViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("国际出港查询")
setBackArrow(if (DeviceUtil.isPhone()) "出港查询" else "国际出港查询")
binding.viewModel = viewModel

View File

@@ -1,90 +1,91 @@
package com.lukouguoji.gjc.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.Gravity
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.appcompat.widget.Toolbar
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.databinding.ActivityGjcQueryDetailsBinding
import com.lukouguoji.gjc.viewModel.GjcQueryDetailsViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.base.CustomVP2Adapter
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.router.ARouterConstants
/**
* 国际出港查询详情页面
*/
@Route(path = ARouterConstants.ACTIVITY_URL_GJC_QUERY_DETAILS)
class GjcQueryDetailsActivity :
BaseBindingActivity<ActivityGjcQueryDetailsBinding, GjcQueryDetailsViewModel>() {
override fun layoutId() = R.layout.activity_gjc_query_details
override fun viewModelClass() = GjcQueryDetailsViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("国际出港查询详情")
binding.viewModel = viewModel
// 初始化ViewModel(传入maWbId)
viewModel.initOnCreated(intent)
// 配置ViewPager2
binding.vp.adapter = CustomVP2Adapter(
viewModel.fragmentList,
supportFragmentManager,
lifecycle
)
binding.vp.isUserInputEnabled = false // 禁用滑动
binding.vp.offscreenPageLimit = 3 // 预加载3个Fragment
// 监听Tab索引变化,切换Fragment
viewModel.currentTab.observe(this) {
binding.vp.setCurrentItem(it, false) // false:无动画
}
// 标题栏右侧添加日志查询图标
val toolbar = findViewById<Toolbar>(com.lukouguoji.module_base.R.id.toolbar)
val logIcon = ImageView(this).apply {
setImageResource(com.lukouguoji.module_base.R.drawable.img_log)
layoutParams = Toolbar.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
).apply {
gravity = Gravity.END or Gravity.CENTER_VERTICAL
marginEnd = 15
width = 30.dp
height = 30.dp
}
setOnClickListener {
val wbNo = viewModel.maWbData.value?.get("wbNo") as? String ?: ""
ARouter.getInstance()
.build(ARouterConstants.ACTIVITY_URL_LOG_DETAIL)
.withString(Constant.Key.KEY, wbNo)
.withString(Constant.Key.AWB_TYPE, "IO")
.navigation()
}
}
toolbar.addView(logIcon)
// 加载详情数据
viewModel.loadDetails()
}
private val Int.dp: Int
get() = (this * resources!!.displayMetrics.density).toInt()
companion object {
@JvmStatic
fun start(context: Context, maWbId: Long?) {
val starter = Intent(context, GjcQueryDetailsActivity::class.java)
.putExtra(Constant.Key.ID, maWbId?.toString() ?: "")
context.startActivity(starter)
}
}
}
package com.lukouguoji.gjc.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.Gravity
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.appcompat.widget.Toolbar
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.databinding.ActivityGjcQueryDetailsBinding
import com.lukouguoji.gjc.viewModel.GjcQueryDetailsViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.base.CustomVP2Adapter
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_GJC_QUERY_DETAILS)
class GjcQueryDetailsActivity :
BaseBindingActivity<ActivityGjcQueryDetailsBinding, GjcQueryDetailsViewModel>() {
override fun layoutId() = R.layout.activity_gjc_query_details
override fun viewModelClass() = GjcQueryDetailsViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow(if (DeviceUtil.isPhone()) "出港货物" else "国际出港查询详情")
binding.viewModel = viewModel
// 初始化ViewModel(传入maWbId)
viewModel.initOnCreated(intent)
// 配置ViewPager2
binding.vp.adapter = CustomVP2Adapter(
viewModel.fragmentList,
supportFragmentManager,
lifecycle
)
binding.vp.isUserInputEnabled = false // 禁用滑动
binding.vp.offscreenPageLimit = 3 // 预加载3个Fragment
// 监听Tab索引变化,切换Fragment
viewModel.currentTab.observe(this) {
binding.vp.setCurrentItem(it, false) // false:无动画
}
// 标题栏右侧添加日志查询图标
val toolbar = findViewById<Toolbar>(com.lukouguoji.module_base.R.id.toolbar)
val logIcon = ImageView(this).apply {
setImageResource(com.lukouguoji.module_base.R.drawable.img_log)
layoutParams = Toolbar.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
).apply {
gravity = Gravity.END or Gravity.CENTER_VERTICAL
marginEnd = 15
width = 30.dp
height = 30.dp
}
setOnClickListener {
val wbNo = viewModel.maWbData.value?.get("wbNo") as? String ?: ""
ARouter.getInstance()
.build(ARouterConstants.ACTIVITY_URL_LOG_DETAIL)
.withString(Constant.Key.KEY, wbNo)
.withString(Constant.Key.AWB_TYPE, "IO")
.navigation()
}
}
toolbar.addView(logIcon)
// 加载详情数据
viewModel.loadDetails()
}
private val Int.dp: Int
get() = (this * resources!!.displayMetrics.density).toInt()
companion object {
@JvmStatic
fun start(context: Context, maWbId: Long?) {
val starter = Intent(context, GjcQueryDetailsActivity::class.java)
.putExtra(Constant.Key.ID, maWbId?.toString() ?: "")
context.startActivity(starter)
}
}
}

View File

@@ -1,105 +1,105 @@
package com.lukouguoji.gjc.activity
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.gjc.R
import com.lukouguoji.gjc.databinding.ActivityGjcWeighingListBinding
import com.lukouguoji.gjc.viewModel.GjcWeighingViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.bean.GjcWeighingBean
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
/**
* 国际出港计重列表页
*
* 布局 id 不区分设备,平板/手机由资源限定符自动选择:
* layout-sw600dp/activity_gjc_weighing_list.xml平板
* layout/activity_gjc_weighing_list.xml手机
*/
@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_LIST)
class GjcWeighingListActivity :
BaseBindingActivity<ActivityGjcWeighingListBinding, GjcWeighingViewModel>() {
override fun layoutId() = R.layout.activity_gjc_weighing_list
override fun viewModelClass() = GjcWeighingViewModel::class.java
/** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */
val filterPanelVisible = ObservableBoolean(false)
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("国际出港待计重")
binding.viewModel = viewModel
binding.activity = this
// 手机版专属数据:放开默认日期、加载筛选弹层字典、启用三格统计
// 平板端不调用,查询链路与请求次数与改造前完全一致
if (DeviceUtil.isPhone()) {
viewModel.initPhoneExtras()
}
// 初始化代理人列表从API获取
viewModel.initAgentList()
// 初始化特码列表从API获取
viewModel.initSpecialCodeList()
// 绑定分页逻辑
viewModel.pageModel
.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner())
// 监听刷新事件
FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { viewModel.onItemCheckChanged() }
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH)
.observe(this) {
viewModel.refresh()
}
// 初始加载
viewModel.refresh()
}
// ==================== 手机版专用交互(纯 UI复用既有 ViewModel 字段) ====================
/** 手机版筛选弹层显隐切换 */
fun toggleFilterPanel() {
filterPanelVisible.set(!filterPanelVisible.get())
}
/** 手机版筛选:重置(只清弹层内条件,不影响顶部搜索框) */
fun resetFilter() {
viewModel.channelFilter.value = ""
viewModel.carrierFilter.value = ""
viewModel.awbTypeFilter.value = ""
viewModel.agentCode.value = ""
}
/** 手机版筛选:确认 */
fun confirmFilter() {
filterPanelVisible.set(false)
viewModel.searchClick()
}
/** 手机版卡片内「提前运抵」(单票,由 ViewHolder 调用) */
fun preArriveClick(bean: GjcWeighingBean) {
viewModel.arrivedAheadSingle(bean)
}
companion object {
@JvmStatic
fun start(context: Context) {
val starter = Intent(context, GjcWeighingListActivity::class.java)
context.startActivity(starter)
}
}
}
package com.lukouguoji.gjc.activity
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.gjc.R
import com.lukouguoji.gjc.databinding.ActivityGjcWeighingListBinding
import com.lukouguoji.gjc.viewModel.GjcWeighingViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.bean.GjcWeighingBean
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
/**
* 国际出港计重列表页
*
* 布局 id 不区分设备,平板/手机由资源限定符自动选择:
* layout-sw600dp/activity_gjc_weighing_list.xml平板
* layout/activity_gjc_weighing_list.xml手机
*/
@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_LIST)
class GjcWeighingListActivity :
BaseBindingActivity<ActivityGjcWeighingListBinding, GjcWeighingViewModel>() {
override fun layoutId() = R.layout.activity_gjc_weighing_list
override fun viewModelClass() = GjcWeighingViewModel::class.java
/** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */
val filterPanelVisible = ObservableBoolean(false)
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow(if (DeviceUtil.isPhone()) "出港待计重" else "国际出港待计重")
binding.viewModel = viewModel
binding.activity = this
// 手机版专属数据:放开默认日期、加载筛选弹层字典、启用三格统计
// 平板端不调用,查询链路与请求次数与改造前完全一致
if (DeviceUtil.isPhone()) {
viewModel.initPhoneExtras()
}
// 初始化代理人列表从API获取
viewModel.initAgentList()
// 初始化特码列表从API获取
viewModel.initSpecialCodeList()
// 绑定分页逻辑
viewModel.pageModel
.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner())
// 监听刷新事件
FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { viewModel.onItemCheckChanged() }
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH)
.observe(this) {
viewModel.refresh()
}
// 初始加载
viewModel.refresh()
}
// ==================== 手机版专用交互(纯 UI复用既有 ViewModel 字段) ====================
/** 手机版筛选弹层显隐切换 */
fun toggleFilterPanel() {
filterPanelVisible.set(!filterPanelVisible.get())
}
/** 手机版筛选:重置(只清弹层内条件,不影响顶部搜索框) */
fun resetFilter() {
viewModel.channelFilter.value = ""
viewModel.carrierFilter.value = ""
viewModel.awbTypeFilter.value = ""
viewModel.agentCode.value = ""
}
/** 手机版筛选:确认 */
fun confirmFilter() {
filterPanelVisible.set(false)
viewModel.searchClick()
}
/** 手机版卡片内「提前运抵」(单票,由 ViewHolder 调用) */
fun preArriveClick(bean: GjcWeighingBean) {
viewModel.arrivedAheadSingle(bean)
}
companion object {
@JvmStatic
fun start(context: Context) {
val starter = Intent(context, GjcWeighingListActivity::class.java)
context.startActivity(starter)
}
}
}

View File

@@ -1,103 +1,104 @@
package com.lukouguoji.gjc.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.alibaba.android.arouter.facade.annotation.Route
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.databinding.ActivityGjcWeighingRecordDetailsBinding
import com.lukouguoji.gjc.holder.GjcCheckInRecordViewHolder
import com.lukouguoji.gjc.viewModel.GjcWeighingRecordDetailsViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.base.CommonAdapter
import com.lukouguoji.module_base.bean.GjcCheckInRecord
import com.lukouguoji.module_base.bean.GjcWeighingRecordBean
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.router.ARouterConstants
/**
* 国际出港计重明细页
*
* 布局 id 不区分设备,平板/手机由资源限定符自动选择:
* layout-sw600dp/activity_gjc_weighing_record_details.xml平板列表内联编辑
* layout/activity_gjc_weighing_record_details.xml手机,单条记录经全屏「修改记录」覆层编辑)
*/
@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_DETAILS)
class GjcWeighingRecordDetailsActivity :
BaseBindingActivity<ActivityGjcWeighingRecordDetailsBinding, GjcWeighingRecordDetailsViewModel>() {
private lateinit var adapter: CommonAdapter
// 当前编辑模式供ViewHolder获取
var currentEditMode = false
override fun layoutId() = R.layout.activity_gjc_weighing_record_details
override fun viewModelClass() = GjcWeighingRecordDetailsViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("国际出港计重明细")
binding.viewModel = viewModel
// 初始化RecyclerView
val layoutManager = LinearLayoutManager(this)
binding.recyclerView.layoutManager = layoutManager
// 添加分割线
val divider = DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
binding.recyclerView.addItemDecoration(divider)
adapter = CommonAdapter(
this,
R.layout.item_gjc_check_in_record,
GjcCheckInRecordViewHolder::class.java
)
binding.recyclerView.adapter = adapter
// 监听数据变化更新RecyclerView
viewModel.recordList.observe(this) { records ->
adapter.refresh(records)
}
// 监听编辑模式变化,更新当前编辑模式并刷新列表
viewModel.isEditMode.observe(this) { isEditMode ->
// 更新当前编辑模式状态
currentEditMode = isEditMode
// 刷新所有可见的 ViewHolder
adapter.notifyDataSetChanged()
}
// 初始化数据
viewModel.initOnCreated(intent)
}
// ==================== 手机版专用交互(纯 UI复用既有 ViewModel 编辑链路) ====================
/**
* 手机版:打开「修改记录」覆层编辑指定记录。
* 复用 [GjcWeighingRecordDetailsViewModel.onModifyClick] 的备份/编辑态逻辑,
* 覆层显隐由 isEditMode 驱动(平板端该状态驱动列表内联编辑,互不影响)。
*/
fun openPhoneEdit(record: GjcCheckInRecord) {
viewModel.onModifyClick()
binding.editRecord = record
}
/** 手机版:取消编辑(恢复备份并收起覆层) */
fun closePhoneEdit() {
viewModel.onCancelClick()
}
companion object {
@JvmStatic
fun start(context: Context, bean: GjcWeighingRecordBean) {
val starter = Intent(context, GjcWeighingRecordDetailsActivity::class.java)
.putExtra(Constant.Key.BEAN, bean)
context.startActivity(starter)
}
}
}
package com.lukouguoji.gjc.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.alibaba.android.arouter.facade.annotation.Route
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.databinding.ActivityGjcWeighingRecordDetailsBinding
import com.lukouguoji.gjc.holder.GjcCheckInRecordViewHolder
import com.lukouguoji.gjc.viewModel.GjcWeighingRecordDetailsViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.base.CommonAdapter
import com.lukouguoji.module_base.bean.GjcCheckInRecord
import com.lukouguoji.module_base.bean.GjcWeighingRecordBean
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.router.ARouterConstants
import com.lukouguoji.module_base.util.DeviceUtil
/**
* 国际出港计重明细页
*
* 布局 id 不区分设备,平板/手机由资源限定符自动选择:
* layout-sw600dp/activity_gjc_weighing_record_details.xml平板,列表内联编辑)
* layout/activity_gjc_weighing_record_details.xml手机单条记录经全屏「修改记录」覆层编辑
*/
@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_DETAILS)
class GjcWeighingRecordDetailsActivity :
BaseBindingActivity<ActivityGjcWeighingRecordDetailsBinding, GjcWeighingRecordDetailsViewModel>() {
private lateinit var adapter: CommonAdapter
// 当前编辑模式供ViewHolder获取
var currentEditMode = false
override fun layoutId() = R.layout.activity_gjc_weighing_record_details
override fun viewModelClass() = GjcWeighingRecordDetailsViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow(if (DeviceUtil.isPhone()) "计重明细" else "国际出港计重明细")
binding.viewModel = viewModel
// 初始化RecyclerView
val layoutManager = LinearLayoutManager(this)
binding.recyclerView.layoutManager = layoutManager
// 添加分割线
val divider = DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
binding.recyclerView.addItemDecoration(divider)
adapter = CommonAdapter(
this,
R.layout.item_gjc_check_in_record,
GjcCheckInRecordViewHolder::class.java
)
binding.recyclerView.adapter = adapter
// 监听数据变化更新RecyclerView
viewModel.recordList.observe(this) { records ->
adapter.refresh(records)
}
// 监听编辑模式变化,更新当前编辑模式并刷新列表
viewModel.isEditMode.observe(this) { isEditMode ->
// 更新当前编辑模式状态
currentEditMode = isEditMode
// 刷新所有可见的 ViewHolder
adapter.notifyDataSetChanged()
}
// 初始化数据
viewModel.initOnCreated(intent)
}
// ==================== 手机版专用交互(纯 UI复用既有 ViewModel 编辑链路) ====================
/**
* 手机版:打开「修改记录」覆层编辑指定记录。
* 复用 [GjcWeighingRecordDetailsViewModel.onModifyClick] 的备份/编辑态逻辑,
* 覆层显隐由 isEditMode 驱动(平板端该状态驱动列表内联编辑,互不影响)。
*/
fun openPhoneEdit(record: GjcCheckInRecord) {
viewModel.onModifyClick()
binding.editRecord = record
}
/** 手机版:取消编辑(恢复备份并收起覆层) */
fun closePhoneEdit() {
viewModel.onCancelClick()
}
companion object {
@JvmStatic
fun start(context: Context, bean: GjcWeighingRecordBean) {
val starter = Intent(context, GjcWeighingRecordDetailsActivity::class.java)
.putExtra(Constant.Key.BEAN, bean)
context.startActivity(starter)
}
}
}

View File

@@ -1,99 +1,99 @@
package com.lukouguoji.gjc.activity
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.gjc.R
import com.lukouguoji.gjc.databinding.ActivityGjcWeighingRecordListBinding
import com.lukouguoji.gjc.viewModel.GjcWeighingRecordViewModel
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.getLifecycleOwner
import com.lukouguoji.module_base.router.ARouterConstants
import com.lukouguoji.module_base.util.DeviceUtil
/**
* 国际出港计重记录列表页
*
* 布局 id 不区分设备,平板/手机由资源限定符自动选择:
* layout-sw600dp/activity_gjc_weighing_record_list.xml平板
* layout/activity_gjc_weighing_record_list.xml手机
*/
@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_LIST)
class GjcWeighingRecordListActivity :
BaseBindingActivity<ActivityGjcWeighingRecordListBinding, GjcWeighingRecordViewModel>() {
override fun layoutId() = R.layout.activity_gjc_weighing_record_list
override fun viewModelClass() = GjcWeighingRecordViewModel::class.java
/** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */
val filterPanelVisible = ObservableBoolean(false)
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("国际出港计重记录")
binding.viewModel = viewModel
binding.activity = this
// 手机版专属数据:放开默认日期、加载计重人下拉
// 平板端不调用,查询链路与请求次数与改造前完全一致
if (DeviceUtil.isPhone()) {
viewModel.initPhoneExtras()
}
// 初始化代理人列表
viewModel.initAgentList()
// 初始化特码列表
viewModel.initSpecialCodeList()
// 绑定分页逻辑
viewModel.pageModel
.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner())
// 监听刷新事件
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH)
.observe(this) {
viewModel.refresh()
}
// 初始加载
viewModel.refresh()
}
// ==================== 手机版专用交互(纯 UI复用既有 ViewModel 字段) ====================
/** 手机版筛选弹层显隐切换 */
fun toggleFilterPanel() {
filterPanelVisible.set(!filterPanelVisible.get())
}
/** 手机版筛选:重置(只清弹层内条件,不影响顶部搜索框) */
fun resetFilter() {
viewModel.checkInDateStart.value = ""
viewModel.checkInDateEnd.value = ""
viewModel.agentCode.value = ""
viewModel.spCode.value = ""
viewModel.destFilter.value = ""
viewModel.opUserFilter.value = ""
}
/** 手机版筛选:确认 */
fun confirmFilter() {
filterPanelVisible.set(false)
viewModel.searchClick()
}
companion object {
@JvmStatic
fun start(context: Context) {
val starter = Intent(context, GjcWeighingRecordListActivity::class.java)
context.startActivity(starter)
}
}
}
package com.lukouguoji.gjc.activity
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.gjc.R
import com.lukouguoji.gjc.databinding.ActivityGjcWeighingRecordListBinding
import com.lukouguoji.gjc.viewModel.GjcWeighingRecordViewModel
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.getLifecycleOwner
import com.lukouguoji.module_base.router.ARouterConstants
import com.lukouguoji.module_base.util.DeviceUtil
/**
* 国际出港计重记录列表页
*
* 布局 id 不区分设备,平板/手机由资源限定符自动选择:
* layout-sw600dp/activity_gjc_weighing_record_list.xml平板
* layout/activity_gjc_weighing_record_list.xml手机
*/
@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_LIST)
class GjcWeighingRecordListActivity :
BaseBindingActivity<ActivityGjcWeighingRecordListBinding, GjcWeighingRecordViewModel>() {
override fun layoutId() = R.layout.activity_gjc_weighing_record_list
override fun viewModelClass() = GjcWeighingRecordViewModel::class.java
/** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */
val filterPanelVisible = ObservableBoolean(false)
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow(if (DeviceUtil.isPhone()) "计重记录" else "国际出港计重记录")
binding.viewModel = viewModel
binding.activity = this
// 手机版专属数据:放开默认日期、加载计重人下拉
// 平板端不调用,查询链路与请求次数与改造前完全一致
if (DeviceUtil.isPhone()) {
viewModel.initPhoneExtras()
}
// 初始化代理人列表
viewModel.initAgentList()
// 初始化特码列表
viewModel.initSpecialCodeList()
// 绑定分页逻辑
viewModel.pageModel
.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner())
// 监听刷新事件
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH)
.observe(this) {
viewModel.refresh()
}
// 初始加载
viewModel.refresh()
}
// ==================== 手机版专用交互(纯 UI复用既有 ViewModel 字段) ====================
/** 手机版筛选弹层显隐切换 */
fun toggleFilterPanel() {
filterPanelVisible.set(!filterPanelVisible.get())
}
/** 手机版筛选:重置(只清弹层内条件,不影响顶部搜索框) */
fun resetFilter() {
viewModel.checkInDateStart.value = ""
viewModel.checkInDateEnd.value = ""
viewModel.agentCode.value = ""
viewModel.spCode.value = ""
viewModel.destFilter.value = ""
viewModel.opUserFilter.value = ""
}
/** 手机版筛选:确认 */
fun confirmFilter() {
filterPanelVisible.set(false)
viewModel.searchClick()
}
companion object {
@JvmStatic
fun start(context: Context) {
val starter = Intent(context, GjcWeighingRecordListActivity::class.java)
context.startActivity(starter)
}
}
}

View File

@@ -1,221 +1,221 @@
package com.lukouguoji.gjc.activity
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
import com.alibaba.android.arouter.facade.annotation.Route
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.databinding.ActivityGjcWeighingStartBinding
import com.lukouguoji.gjc.viewModel.GjcWeighingStartViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
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_GJC_WEIGHING_START)
class GjcWeighingStartActivity :
BaseBindingActivity<ActivityGjcWeighingStartBinding, GjcWeighingStartViewModel>() {
private var isExpanded = false
override fun layoutId() = R.layout.activity_gjc_weighing_start
override fun viewModelClass() = GjcWeighingStartViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("国际出港开始计重")
binding.viewModel = viewModel
// 手机版专属:提交体携带托盘数量/托盘自重(平板不调用,请求体与改造前完全一致)
if (DeviceUtil.isPhone()) {
viewModel.initPhoneExtras()
}
viewModel.initOnCreated(this, intent)
setupFloatButtons()
}
private fun setupFloatButtons() {
// 浮动按钮组仅平板布局存在layout-sw600dp手机布局无这些 id直接跳过
val mainFloatButton = binding.mainFloatButton ?: return
val maskView = binding.maskView ?: return
val subButton1 = binding.subButton1 ?: return
val subButton2 = binding.subButton2 ?: return
// 主按钮点击事件
mainFloatButton.setOnClickListener {
if (!isExpanded) {
expandButtons()
}
}
// 遮罩层点击事件
maskView.setOnClickListener {
collapseButtons()
}
// 子按钮1点击事件 - 跳转到出港运抵页面
subButton1.setOnClickListener {
com.alibaba.android.arouter.launcher.ARouter.getInstance()
.build(ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE)
.navigation()
collapseButtons()
}
// 子按钮2点击事件 - 跳转到计重记录
subButton2.setOnClickListener {
com.alibaba.android.arouter.launcher.ARouter.getInstance()
.build(ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_LIST)
.navigation()
collapseButtons()
}
}
/**
* 展开子按钮(仅平板,手机布局无浮动按钮组)
*/
private fun expandButtons() {
val mainFloatButton = binding.mainFloatButton ?: return
val maskView = binding.maskView ?: return
val subButton1 = binding.subButton1 ?: return
val subButton2 = binding.subButton2 ?: return
isExpanded = true
// 显示遮罩层
maskView.visibility = View.VISIBLE
maskView.alpha = 0f
maskView.animate().alpha(0.3f).setDuration(200).start()
// 显示子按钮
subButton1.visibility = View.VISIBLE
subButton2.visibility = View.VISIBLE
// 子按钮1动画向左上方移动: 左移15dp, 上移55dp
val sub1TransX = ObjectAnimator.ofFloat(subButton1, "translationX", 0f, -5f)
val sub1TransY = ObjectAnimator.ofFloat(subButton1, "translationY", 0f, -25f)
val sub1Alpha = ObjectAnimator.ofFloat(subButton1, "alpha", 0f, 1f)
val sub1Scale = ObjectAnimator.ofFloat(subButton1, "scaleX", 0f, 1f)
val sub1ScaleY = ObjectAnimator.ofFloat(subButton1, "scaleY", 0f, 1f)
val animSet1 = AnimatorSet()
animSet1.playTogether(sub1TransX, sub1TransY, sub1Alpha, sub1Scale, sub1ScaleY)
animSet1.duration = 200
// 子按钮2动画向左下方移动: 左移55dp, 下移15dp
val sub2TransX = ObjectAnimator.ofFloat(subButton2, "translationX", 0f, -25f)
val sub2TransY = ObjectAnimator.ofFloat(subButton2, "translationY", 0f, -5f)
val sub2Alpha = ObjectAnimator.ofFloat(subButton2, "alpha", 0f, 1f)
val sub2Scale = ObjectAnimator.ofFloat(subButton2, "scaleX", 0f, 1f)
val sub2ScaleY = ObjectAnimator.ofFloat(subButton2, "scaleY", 0f, 1f)
val animSet2 = AnimatorSet()
animSet2.playTogether(sub2TransX, sub2TransY, sub2Alpha, sub2Scale, sub2ScaleY)
animSet2.duration = 200
animSet2.startDelay = 50
// 主按钮隐藏动画
mainFloatButton.animate()
.scaleX(0f)
.scaleY(0f)
.alpha(0f)
.setDuration(150)
.setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
mainFloatButton.visibility = View.GONE
}
})
.start()
animSet1.start()
animSet2.start()
}
/**
* 收起子按钮(仅平板,手机布局无浮动按钮组)
*/
private fun collapseButtons() {
val mainFloatButton = binding.mainFloatButton ?: return
val maskView = binding.maskView ?: return
val subButton1 = binding.subButton1 ?: return
val subButton2 = binding.subButton2 ?: return
isExpanded = false
// 隐藏遮罩层
maskView.animate().alpha(0f).setDuration(200).withEndAction {
maskView.visibility = View.GONE
}.start()
// 子按钮1动画回到原位
val sub1TransX = ObjectAnimator.ofFloat(subButton1, "translationX", subButton1.translationX, 0f)
val sub1TransY = ObjectAnimator.ofFloat(subButton1, "translationY", subButton1.translationY, 0f)
val sub1Alpha = ObjectAnimator.ofFloat(subButton1, "alpha", 1f, 0f)
val sub1Scale = ObjectAnimator.ofFloat(subButton1, "scaleX", 1f, 0f)
val sub1ScaleY = ObjectAnimator.ofFloat(subButton1, "scaleY", 1f, 0f)
val animSet1 = AnimatorSet()
animSet1.playTogether(sub1TransX, sub1TransY, sub1Alpha, sub1Scale, sub1ScaleY)
animSet1.duration = 200
// 子按钮2动画回到原位
val sub2TransX = ObjectAnimator.ofFloat(subButton2, "translationX", subButton2.translationX, 0f)
val sub2TransY = ObjectAnimator.ofFloat(subButton2, "translationY", subButton2.translationY, 0f)
val sub2Alpha = ObjectAnimator.ofFloat(subButton2, "alpha", 1f, 0f)
val sub2Scale = ObjectAnimator.ofFloat(subButton2, "scaleX", 1f, 0f)
val sub2ScaleY = ObjectAnimator.ofFloat(subButton2, "scaleY", 1f, 0f)
val animSet2 = AnimatorSet()
animSet2.playTogether(sub2TransX, sub2TransY, sub2Alpha, sub2Scale, sub2ScaleY)
animSet2.duration = 200
animSet1.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
subButton1.visibility = View.GONE
}
})
animSet2.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
subButton2.visibility = View.GONE
}
})
// 主按钮显示动画
mainFloatButton.visibility = View.VISIBLE
mainFloatButton.animate()
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.setDuration(200)
.setStartDelay(100)
.setListener(null)
.start()
animSet1.start()
animSet2.start()
}
companion object {
/**
* 启动开始计重页面
* @param context 上下文
* @param maWbId 运单ID默认为0新增模式
*/
@JvmStatic
fun startForAdd(context: Context, maWbId: Long = 0) {
val starter = Intent(context, GjcWeighingStartActivity::class.java)
.putExtra(Constant.Key.MAWB_ID, maWbId)
context.startActivity(starter)
}
}
}
package com.lukouguoji.gjc.activity
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
import com.alibaba.android.arouter.facade.annotation.Route
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.databinding.ActivityGjcWeighingStartBinding
import com.lukouguoji.gjc.viewModel.GjcWeighingStartViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
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_GJC_WEIGHING_START)
class GjcWeighingStartActivity :
BaseBindingActivity<ActivityGjcWeighingStartBinding, GjcWeighingStartViewModel>() {
private var isExpanded = false
override fun layoutId() = R.layout.activity_gjc_weighing_start
override fun viewModelClass() = GjcWeighingStartViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow(if (DeviceUtil.isPhone()) "开始计重" else "国际出港开始计重")
binding.viewModel = viewModel
// 手机版专属:提交体携带托盘数量/托盘自重(平板不调用,请求体与改造前完全一致)
if (DeviceUtil.isPhone()) {
viewModel.initPhoneExtras()
}
viewModel.initOnCreated(this, intent)
setupFloatButtons()
}
private fun setupFloatButtons() {
// 浮动按钮组仅平板布局存在layout-sw600dp手机布局无这些 id直接跳过
val mainFloatButton = binding.mainFloatButton ?: return
val maskView = binding.maskView ?: return
val subButton1 = binding.subButton1 ?: return
val subButton2 = binding.subButton2 ?: return
// 主按钮点击事件
mainFloatButton.setOnClickListener {
if (!isExpanded) {
expandButtons()
}
}
// 遮罩层点击事件
maskView.setOnClickListener {
collapseButtons()
}
// 子按钮1点击事件 - 跳转到出港运抵页面
subButton1.setOnClickListener {
com.alibaba.android.arouter.launcher.ARouter.getInstance()
.build(ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE)
.navigation()
collapseButtons()
}
// 子按钮2点击事件 - 跳转到计重记录
subButton2.setOnClickListener {
com.alibaba.android.arouter.launcher.ARouter.getInstance()
.build(ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_LIST)
.navigation()
collapseButtons()
}
}
/**
* 展开子按钮(仅平板,手机布局无浮动按钮组)
*/
private fun expandButtons() {
val mainFloatButton = binding.mainFloatButton ?: return
val maskView = binding.maskView ?: return
val subButton1 = binding.subButton1 ?: return
val subButton2 = binding.subButton2 ?: return
isExpanded = true
// 显示遮罩层
maskView.visibility = View.VISIBLE
maskView.alpha = 0f
maskView.animate().alpha(0.3f).setDuration(200).start()
// 显示子按钮
subButton1.visibility = View.VISIBLE
subButton2.visibility = View.VISIBLE
// 子按钮1动画向左上方移动: 左移15dp, 上移55dp
val sub1TransX = ObjectAnimator.ofFloat(subButton1, "translationX", 0f, -5f)
val sub1TransY = ObjectAnimator.ofFloat(subButton1, "translationY", 0f, -25f)
val sub1Alpha = ObjectAnimator.ofFloat(subButton1, "alpha", 0f, 1f)
val sub1Scale = ObjectAnimator.ofFloat(subButton1, "scaleX", 0f, 1f)
val sub1ScaleY = ObjectAnimator.ofFloat(subButton1, "scaleY", 0f, 1f)
val animSet1 = AnimatorSet()
animSet1.playTogether(sub1TransX, sub1TransY, sub1Alpha, sub1Scale, sub1ScaleY)
animSet1.duration = 200
// 子按钮2动画向左下方移动: 左移55dp, 下移15dp
val sub2TransX = ObjectAnimator.ofFloat(subButton2, "translationX", 0f, -25f)
val sub2TransY = ObjectAnimator.ofFloat(subButton2, "translationY", 0f, -5f)
val sub2Alpha = ObjectAnimator.ofFloat(subButton2, "alpha", 0f, 1f)
val sub2Scale = ObjectAnimator.ofFloat(subButton2, "scaleX", 0f, 1f)
val sub2ScaleY = ObjectAnimator.ofFloat(subButton2, "scaleY", 0f, 1f)
val animSet2 = AnimatorSet()
animSet2.playTogether(sub2TransX, sub2TransY, sub2Alpha, sub2Scale, sub2ScaleY)
animSet2.duration = 200
animSet2.startDelay = 50
// 主按钮隐藏动画
mainFloatButton.animate()
.scaleX(0f)
.scaleY(0f)
.alpha(0f)
.setDuration(150)
.setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
mainFloatButton.visibility = View.GONE
}
})
.start()
animSet1.start()
animSet2.start()
}
/**
* 收起子按钮(仅平板,手机布局无浮动按钮组)
*/
private fun collapseButtons() {
val mainFloatButton = binding.mainFloatButton ?: return
val maskView = binding.maskView ?: return
val subButton1 = binding.subButton1 ?: return
val subButton2 = binding.subButton2 ?: return
isExpanded = false
// 隐藏遮罩层
maskView.animate().alpha(0f).setDuration(200).withEndAction {
maskView.visibility = View.GONE
}.start()
// 子按钮1动画回到原位
val sub1TransX = ObjectAnimator.ofFloat(subButton1, "translationX", subButton1.translationX, 0f)
val sub1TransY = ObjectAnimator.ofFloat(subButton1, "translationY", subButton1.translationY, 0f)
val sub1Alpha = ObjectAnimator.ofFloat(subButton1, "alpha", 1f, 0f)
val sub1Scale = ObjectAnimator.ofFloat(subButton1, "scaleX", 1f, 0f)
val sub1ScaleY = ObjectAnimator.ofFloat(subButton1, "scaleY", 1f, 0f)
val animSet1 = AnimatorSet()
animSet1.playTogether(sub1TransX, sub1TransY, sub1Alpha, sub1Scale, sub1ScaleY)
animSet1.duration = 200
// 子按钮2动画回到原位
val sub2TransX = ObjectAnimator.ofFloat(subButton2, "translationX", subButton2.translationX, 0f)
val sub2TransY = ObjectAnimator.ofFloat(subButton2, "translationY", subButton2.translationY, 0f)
val sub2Alpha = ObjectAnimator.ofFloat(subButton2, "alpha", 1f, 0f)
val sub2Scale = ObjectAnimator.ofFloat(subButton2, "scaleX", 1f, 0f)
val sub2ScaleY = ObjectAnimator.ofFloat(subButton2, "scaleY", 1f, 0f)
val animSet2 = AnimatorSet()
animSet2.playTogether(sub2TransX, sub2TransY, sub2Alpha, sub2Scale, sub2ScaleY)
animSet2.duration = 200
animSet1.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
subButton1.visibility = View.GONE
}
})
animSet2.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
subButton2.visibility = View.GONE
}
})
// 主按钮显示动画
mainFloatButton.visibility = View.VISIBLE
mainFloatButton.animate()
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.setDuration(200)
.setStartDelay(100)
.setListener(null)
.start()
animSet1.start()
animSet2.start()
}
companion object {
/**
* 启动开始计重页面
* @param context 上下文
* @param maWbId 运单ID默认为0新增模式
*/
@JvmStatic
fun startForAdd(context: Context, maWbId: Long = 0) {
val starter = Intent(context, GjcWeighingStartActivity::class.java)
.putExtra(Constant.Key.MAWB_ID, maWbId)
context.startActivity(starter)
}
}
}

View File

@@ -1,177 +1,177 @@
package com.lukouguoji.gjc.activity
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import androidx.databinding.ObservableBoolean
import com.alibaba.android.arouter.facade.annotation.Autowired
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.databinding.ActivityIntExpArriveBinding
import com.lukouguoji.gjc.viewModel.IntExpArriveViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.bean.GjcHaWb
import com.lukouguoji.module_base.bean.GjcMaWb
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.common.ConstantEvent
import com.lukouguoji.module_base.impl.FlowBus
import com.lukouguoji.module_base.impl.observe
import com.lukouguoji.module_base.ktx.addOnItemClickListener
import com.lukouguoji.module_base.ktx.commonAdapter
import com.lukouguoji.module_base.router.ARouterConstants
import com.lukouguoji.module_base.util.DeviceUtil
import java.util.ArrayList
/**
* 国际出港-出港运抵页面
*
* 布局 id 不区分设备,平板/手机由资源限定符自动选择:
* layout-sw600dp/activity_int_exp_arrive.xml平板
* layout/activity_int_exp_arrive.xml手机
*/
@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE)
class IntExpArriveActivity :
BaseBindingActivity<ActivityIntExpArriveBinding, IntExpArriveViewModel>() {
@JvmField
@Autowired
var wbNoParam: String? = null
override fun layoutId() = R.layout.activity_int_exp_arrive
override fun viewModelClass() = IntExpArriveViewModel::class.java
/** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */
val filterPanelVisible = ObservableBoolean(false)
/** 供 [com.lukouguoji.gjc.holder.IntExpArriveViewHolder] 绑定 item 布局的 viewModel 变量(父类 viewModel 为 protected */
val itemViewModel: IntExpArriveViewModel get() = viewModel
override fun initOnCreate(savedInstanceState: Bundle?) {
// 注入 ARouter 参数
ARouter.getInstance().inject(this)
setBackArrow("国际出港运抵")
binding.viewModel = viewModel
binding.activity = this
// 手机版专属数据:加载「代理」筛选下拉
// 平板端不调用,查询链路与请求次数与改造前完全一致
if (DeviceUtil.isPhone()) {
viewModel.initPhoneExtras()
}
// 如果有传入运单号,自动填充并触发搜索
if (!wbNoParam.isNullOrEmpty()) {
viewModel.waybillNo.value = wbNoParam
viewModel.searchClick()
}
// 绑定分页
viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this)
// 设置item点击监听
binding.rv.addOnItemClickListener(viewModel)
// 监听刷新事件
FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { viewModel.onItemCheckChanged() }
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).observe(this) {
viewModel.refresh()
}
// 初始加载数据(如果没有传入运单号,才执行初始加载)
if (wbNoParam.isNullOrEmpty()) {
viewModel.refresh()
}
}
// ==================== 手机版专用交互(纯 UI复用既有 ViewModel 字段与数据) ====================
/**
* 手机版 Tab 切换回调PhoneStatusTab 已通过双向绑定写入 viewModel.currentTab
* 这里触发 ViewModel 把适配器数据集替换为过滤后的子集(不发起新请求)。
*/
fun onArriveTabChanged() {
viewModel.onTabChangedPhone()
}
/** 卡片长按展开操作浮层View.OnLongClickListener 要求返回 Boolean */
fun showCardActionPhone(bean: GjcMaWb): Boolean {
bean.actionMenuVisible.set(true)
return true
}
/** 点击浮层遮罩/空白处:收起操作浮层 */
fun hideCardActionPhone(bean: GjcMaWb) {
bean.actionMenuVisible.set(false)
}
/** 选择圈勾选状态变化后回调(由 ViewHolder 调用) */
fun onItemCheckChanged() {
viewModel.onItemCheckChanged()
}
/** 手机版筛选弹层显隐切换 */
fun toggleFilterPanel() {
filterPanelVisible.set(!filterPanelVisible.get())
}
/** 手机版筛选:重置 */
fun resetFilter() {
viewModel.flightDate.value = ""
viewModel.flightNo.value = ""
viewModel.agentCodePhone.value = ""
}
/** 手机版筛选:确认 */
fun confirmFilter() {
filterPanelVisible.set(false)
viewModel.searchClick()
}
/**
* 进入「分单明细」页:直接传递该运单已加载的 haWbList零新增请求。
*/
fun openSubOrder(bean: GjcMaWb) {
val list = ArrayList<GjcHaWb>(bean.haWbList.orEmpty())
IntExpArriveSubOrderActivity.start(this, bean.wbNo.orEmpty(), list)
}
/**
* 进入「回执」页(手机专属只读页):复用 haWbList[].response + arrivalOpDate零新增请求。
*/
fun openReceipt(bean: GjcMaWb) {
bean.actionMenuVisible.set(false)
val list = ArrayList<GjcHaWb>(bean.haWbList.orEmpty())
IntExpArriveReceiptActivity.start(this, bean.wbNo.orEmpty(), list)
}
/**
* 进入「补充信息」页(手机专属新页):对该运单整个 haWbList 批量应用(参照 Pad 端国际进港
* IntArrSupplementInfoViewModel 的批量复制模式)。后端暂无保存接口,见接口问题清单。
*/
fun openSupplement(bean: GjcMaWb) {
bean.actionMenuVisible.set(false)
val list = ArrayList<GjcHaWb>(bean.haWbList.orEmpty())
IntExpArriveSupplementActivity.start(this, bean.wbNo.orEmpty(), list)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
Constant.RequestCode.WAYBILL -> {
if (resultCode == Activity.RESULT_OK) {
viewModel.waybillNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT)
viewModel.searchClick()
}
}
Constant.RequestCode.CODE -> {
if (resultCode == Activity.RESULT_OK) {
viewModel.hno.value = data?.getStringExtra(Constant.Result.CODED_CONTENT)
viewModel.searchClick()
}
}
}
}
}
package com.lukouguoji.gjc.activity
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import androidx.databinding.ObservableBoolean
import com.alibaba.android.arouter.facade.annotation.Autowired
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.databinding.ActivityIntExpArriveBinding
import com.lukouguoji.gjc.viewModel.IntExpArriveViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.bean.GjcHaWb
import com.lukouguoji.module_base.bean.GjcMaWb
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.common.ConstantEvent
import com.lukouguoji.module_base.impl.FlowBus
import com.lukouguoji.module_base.impl.observe
import com.lukouguoji.module_base.ktx.addOnItemClickListener
import com.lukouguoji.module_base.ktx.commonAdapter
import com.lukouguoji.module_base.router.ARouterConstants
import com.lukouguoji.module_base.util.DeviceUtil
import java.util.ArrayList
/**
* 国际出港-出港运抵页面
*
* 布局 id 不区分设备,平板/手机由资源限定符自动选择:
* layout-sw600dp/activity_int_exp_arrive.xml平板
* layout/activity_int_exp_arrive.xml手机
*/
@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE)
class IntExpArriveActivity :
BaseBindingActivity<ActivityIntExpArriveBinding, IntExpArriveViewModel>() {
@JvmField
@Autowired
var wbNoParam: String? = null
override fun layoutId() = R.layout.activity_int_exp_arrive
override fun viewModelClass() = IntExpArriveViewModel::class.java
/** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */
val filterPanelVisible = ObservableBoolean(false)
/** 供 [com.lukouguoji.gjc.holder.IntExpArriveViewHolder] 绑定 item 布局的 viewModel 变量(父类 viewModel 为 protected */
val itemViewModel: IntExpArriveViewModel get() = viewModel
override fun initOnCreate(savedInstanceState: Bundle?) {
// 注入 ARouter 参数
ARouter.getInstance().inject(this)
setBackArrow(if (DeviceUtil.isPhone()) "出港运抵" else "国际出港运抵")
binding.viewModel = viewModel
binding.activity = this
// 手机版专属数据:加载「代理」筛选下拉
// 平板端不调用,查询链路与请求次数与改造前完全一致
if (DeviceUtil.isPhone()) {
viewModel.initPhoneExtras()
}
// 如果有传入运单号,自动填充并触发搜索
if (!wbNoParam.isNullOrEmpty()) {
viewModel.waybillNo.value = wbNoParam
viewModel.searchClick()
}
// 绑定分页
viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this)
// 设置item点击监听
binding.rv.addOnItemClickListener(viewModel)
// 监听刷新事件
FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { viewModel.onItemCheckChanged() }
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).observe(this) {
viewModel.refresh()
}
// 初始加载数据(如果没有传入运单号,才执行初始加载)
if (wbNoParam.isNullOrEmpty()) {
viewModel.refresh()
}
}
// ==================== 手机版专用交互(纯 UI复用既有 ViewModel 字段与数据) ====================
/**
* 手机版 Tab 切换回调PhoneStatusTab 已通过双向绑定写入 viewModel.currentTab
* 这里触发 ViewModel 把适配器数据集替换为过滤后的子集(不发起新请求)。
*/
fun onArriveTabChanged() {
viewModel.onTabChangedPhone()
}
/** 卡片长按展开操作浮层View.OnLongClickListener 要求返回 Boolean */
fun showCardActionPhone(bean: GjcMaWb): Boolean {
bean.actionMenuVisible.set(true)
return true
}
/** 点击浮层遮罩/空白处:收起操作浮层 */
fun hideCardActionPhone(bean: GjcMaWb) {
bean.actionMenuVisible.set(false)
}
/** 选择圈勾选状态变化后回调(由 ViewHolder 调用) */
fun onItemCheckChanged() {
viewModel.onItemCheckChanged()
}
/** 手机版筛选弹层显隐切换 */
fun toggleFilterPanel() {
filterPanelVisible.set(!filterPanelVisible.get())
}
/** 手机版筛选:重置 */
fun resetFilter() {
viewModel.flightDate.value = ""
viewModel.flightNo.value = ""
viewModel.agentCodePhone.value = ""
}
/** 手机版筛选:确认 */
fun confirmFilter() {
filterPanelVisible.set(false)
viewModel.searchClick()
}
/**
* 进入「分单明细」页:直接传递该运单已加载的 haWbList零新增请求。
*/
fun openSubOrder(bean: GjcMaWb) {
val list = ArrayList<GjcHaWb>(bean.haWbList.orEmpty())
IntExpArriveSubOrderActivity.start(this, bean.wbNo.orEmpty(), list)
}
/**
* 进入「回执」页(手机专属只读页):复用 haWbList[].response + arrivalOpDate零新增请求。
*/
fun openReceipt(bean: GjcMaWb) {
bean.actionMenuVisible.set(false)
val list = ArrayList<GjcHaWb>(bean.haWbList.orEmpty())
IntExpArriveReceiptActivity.start(this, bean.wbNo.orEmpty(), list)
}
/**
* 进入「补充信息」页(手机专属新页):对该运单整个 haWbList 批量应用(参照 Pad 端国际进港
* IntArrSupplementInfoViewModel 的批量复制模式)。后端暂无保存接口,见接口问题清单。
*/
fun openSupplement(bean: GjcMaWb) {
bean.actionMenuVisible.set(false)
val list = ArrayList<GjcHaWb>(bean.haWbList.orEmpty())
IntExpArriveSupplementActivity.start(this, bean.wbNo.orEmpty(), list)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
Constant.RequestCode.WAYBILL -> {
if (resultCode == Activity.RESULT_OK) {
viewModel.waybillNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT)
viewModel.searchClick()
}
}
Constant.RequestCode.CODE -> {
if (resultCode == Activity.RESULT_OK) {
viewModel.hno.value = data?.getStringExtra(Constant.Result.CODED_CONTENT)
viewModel.searchClick()
}
}
}
}
}

View File

@@ -35,7 +35,7 @@ class IntExpOutHandoverActivity :
val filterPanelVisible = ObservableBoolean(false)
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("国际出港出库交接")
setBackArrow(if (DeviceUtil.isPhone()) "出库交接" else "国际出港出库交接")
binding.viewModel = viewModel
binding.activity = this

View File

@@ -1,171 +1,171 @@
package com.lukouguoji.gjc.page.move
import android.app.Activity
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.gjc.R
import com.lukouguoji.gjc.databinding.ActivityIntExpMoveBinding
import com.lukouguoji.gjc.viewModel.IntExpMoveViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.common.ConstantEvent
import com.lukouguoji.module_base.impl.FlowBus
import com.lukouguoji.module_base.impl.observe
import com.lukouguoji.module_base.ktx.addOnItemClickListener
import com.lukouguoji.module_base.ktx.showToast
import com.lukouguoji.module_base.model.ConfirmDialogModel
import com.lukouguoji.module_base.model.ScanModel
import com.lukouguoji.module_base.router.ARouterConstants
import com.lukouguoji.module_base.util.DeviceUtil
/**
* 国际出港-出港移库
*/
@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_MOVE)
class IntExpMoveActivity : BaseBindingActivity<ActivityIntExpMoveBinding, IntExpMoveViewModel>() {
// 布局 id 不区分设备,平板/手机由资源限定符自动选择:
// layout-sw600dp/activity_int_exp_move.xml平板 / layout/activity_int_exp_move.xml手机
override fun layoutId() = R.layout.activity_int_exp_move
override fun viewModelClass() = IntExpMoveViewModel::class.java
/** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */
val filterPanelVisible = ObservableBoolean(false)
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("国际出港移库")
binding.viewModel = viewModel
binding.activity = this
// 手机版专属数据默认「待移库」Tab、Tab 角标计数、特码下拉
// 平板端不调用,查询链路与请求次数与改造前完全一致
if (DeviceUtil.isPhone()) {
viewModel.initPhoneExtras()
}
initRecyclerView()
initListeners()
observeData()
}
/**
* 初始化RecyclerView
*/
private fun initRecyclerView() {
viewModel.pageModel.bindSmartRefreshLayout(
binding.srl,
binding.rv,
viewModel,
this
)
binding.rv.addOnItemClickListener(viewModel)
}
/**
* 初始化监听器
*/
private fun initListeners() {
// 移库按钮btnMove 只存在于平板变体(手机版底部条走 setOnActionClick故判空
binding.btnMove?.setOnClickListener {
showMoveConfirmDialog()
}
}
/**
* 观察数据变化
*/
private fun observeData() {
// 监听item选择变化事件,更新全选状态
FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) {
viewModel.onItemCheckChanged()
}
// 监听刷新事件
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).observe(this) {
viewModel.refresh()
}
// 初始加载数据
viewModel.refresh()
}
/**
* 扫码运单号
*/
fun scanWaybill() {
ScanModel.startScan(this, Constant.RequestCode.WAYBILL)
}
// ==================== 手机版专用交互(复用既有 ViewModel 字段,无新增业务逻辑) ====================
/**
* 手机版筛选弹层显隐切换
*/
fun toggleFilterPanel() {
filterPanelVisible.set(!filterPanelVisible.get())
}
/**
* 手机版筛选:重置
*
* 只清空弹层内的三个条件(承运人 / 运单类型 / 特码),不影响 Tab 与顶部搜索框。
*/
fun resetFilter() {
viewModel.by1.value = ""
viewModel.awbType.value = ""
viewModel.spCode.value = ""
}
/**
* 手机版筛选:确定
*/
fun confirmFilter() {
filterPanelVisible.set(false)
viewModel.searchClick()
}
/**
* 显示移库确认对话框
*
* 手机版底部操作条通过 XML 的 setOnActionClick 调用,故为 public。
*/
fun showMoveConfirmDialog() {
val selectedItems = viewModel.getSelectedItems()
if (selectedItems.isEmpty()) {
showToast("请至少选择一条运单")
return
}
ConfirmDialogModel(
message = "确定要移库选中的 ${selectedItems.size} 条运单吗?",
title = "移库确认"
) {
viewModel.submitMove()
}.show()
}
/**
* 扫码回调
*/
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == Constant.RequestCode.WAYBILL && resultCode == Activity.RESULT_OK) {
val code = data?.getStringExtra(Constant.Result.CODED_CONTENT)
viewModel.waybillNo.value = code
viewModel.searchClick()
}
}
companion object {
@JvmStatic
fun start(context: Context) {
val starter = Intent(context, IntExpMoveActivity::class.java)
context.startActivity(starter)
}
}
}
package com.lukouguoji.gjc.page.move
import android.app.Activity
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.gjc.R
import com.lukouguoji.gjc.databinding.ActivityIntExpMoveBinding
import com.lukouguoji.gjc.viewModel.IntExpMoveViewModel
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.common.ConstantEvent
import com.lukouguoji.module_base.impl.FlowBus
import com.lukouguoji.module_base.impl.observe
import com.lukouguoji.module_base.ktx.addOnItemClickListener
import com.lukouguoji.module_base.ktx.showToast
import com.lukouguoji.module_base.model.ConfirmDialogModel
import com.lukouguoji.module_base.model.ScanModel
import com.lukouguoji.module_base.router.ARouterConstants
import com.lukouguoji.module_base.util.DeviceUtil
/**
* 国际出港-出港移库
*/
@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_MOVE)
class IntExpMoveActivity : BaseBindingActivity<ActivityIntExpMoveBinding, IntExpMoveViewModel>() {
// 布局 id 不区分设备,平板/手机由资源限定符自动选择:
// layout-sw600dp/activity_int_exp_move.xml平板 / layout/activity_int_exp_move.xml手机
override fun layoutId() = R.layout.activity_int_exp_move
override fun viewModelClass() = IntExpMoveViewModel::class.java
/** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */
val filterPanelVisible = ObservableBoolean(false)
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow(if (DeviceUtil.isPhone()) "出港移库" else "国际出港移库")
binding.viewModel = viewModel
binding.activity = this
// 手机版专属数据默认「待移库」Tab、Tab 角标计数、特码下拉
// 平板端不调用,查询链路与请求次数与改造前完全一致
if (DeviceUtil.isPhone()) {
viewModel.initPhoneExtras()
}
initRecyclerView()
initListeners()
observeData()
}
/**
* 初始化RecyclerView
*/
private fun initRecyclerView() {
viewModel.pageModel.bindSmartRefreshLayout(
binding.srl,
binding.rv,
viewModel,
this
)
binding.rv.addOnItemClickListener(viewModel)
}
/**
* 初始化监听器
*/
private fun initListeners() {
// 移库按钮btnMove 只存在于平板变体(手机版底部条走 setOnActionClick故判空
binding.btnMove?.setOnClickListener {
showMoveConfirmDialog()
}
}
/**
* 观察数据变化
*/
private fun observeData() {
// 监听item选择变化事件,更新全选状态
FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) {
viewModel.onItemCheckChanged()
}
// 监听刷新事件
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).observe(this) {
viewModel.refresh()
}
// 初始加载数据
viewModel.refresh()
}
/**
* 扫码运单号
*/
fun scanWaybill() {
ScanModel.startScan(this, Constant.RequestCode.WAYBILL)
}
// ==================== 手机版专用交互(复用既有 ViewModel 字段,无新增业务逻辑) ====================
/**
* 手机版筛选弹层显隐切换
*/
fun toggleFilterPanel() {
filterPanelVisible.set(!filterPanelVisible.get())
}
/**
* 手机版筛选:重置
*
* 只清空弹层内的三个条件(承运人 / 运单类型 / 特码),不影响 Tab 与顶部搜索框。
*/
fun resetFilter() {
viewModel.by1.value = ""
viewModel.awbType.value = ""
viewModel.spCode.value = ""
}
/**
* 手机版筛选:确定
*/
fun confirmFilter() {
filterPanelVisible.set(false)
viewModel.searchClick()
}
/**
* 显示移库确认对话框
*
* 手机版底部操作条通过 XML 的 setOnActionClick 调用,故为 public。
*/
fun showMoveConfirmDialog() {
val selectedItems = viewModel.getSelectedItems()
if (selectedItems.isEmpty()) {
showToast("请至少选择一条运单")
return
}
ConfirmDialogModel(
message = "确定要移库选中的 ${selectedItems.size} 条运单吗?",
title = "移库确认"
) {
viewModel.submitMove()
}.show()
}
/**
* 扫码回调
*/
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == Constant.RequestCode.WAYBILL && resultCode == Activity.RESULT_OK) {
val code = data?.getStringExtra(Constant.Result.CODED_CONTENT)
viewModel.waybillNo.value = code
viewModel.searchClick()
}
}
companion object {
@JvmStatic
fun start(context: Context) {
val starter = Intent(context, IntExpMoveActivity::class.java)
context.startActivity(starter)
}
}
}

View File

@@ -75,23 +75,51 @@
android:layout_marginTop="12dp"
android:orientation="horizontal">
<TextView
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"日期: " + bean.fdate}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="日期: 20260721" />
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_airplane" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:text='@{"日期: " + bean.fdate}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="日期: 20260721" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"航程: " + bean.range}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="航程: HFE-LAX" />
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="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:text='@{"航程: " + bean.range}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="航程: HFE-LAX" />
</LinearLayout>
</LinearLayout>
@@ -102,23 +130,54 @@
android:layout_marginTop="8dp"
android:orientation="horizontal">
<TextView
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"代理: " + bean.agentName}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="代理: 中外运" />
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_person" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:text='@{"代理: " + bean.agentName}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="代理: 中外运" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"特码: " + bean.spCode}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="特码: DGR" />
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_tag" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:text='@{"特码: " + bean.spCode}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="特码: DGR" />
</LinearLayout>
</LinearLayout>

View File

@@ -56,14 +56,28 @@
</LinearLayout>
<!-- 代理 -->
<TextView
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text='@{"代理: " + bean.agentName}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="代理: 马道" />
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_person" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:text='@{"代理: " + bean.agentName}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="代理: 马道" />
</LinearLayout>
<!-- 运抵统计框 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneStatBox

View File

@@ -33,7 +33,7 @@ class IntImpQueryActivity :
override fun viewModelClass() = IntImpQueryViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("国际进港查询")
setBackArrow(if (DeviceUtil.isPhone()) "进港查询" else "国际进港查询")
binding.viewModel = viewModel

View File

@@ -16,6 +16,7 @@ import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.base.CustomVP2Adapter
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.router.ARouterConstants
import com.lukouguoji.module_base.util.DeviceUtil
/**
* 国际进港查询详情页面
@@ -28,7 +29,7 @@ class IntImpQueryDetailsActivity :
override fun viewModelClass() = IntImpQueryDetailsViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("国际进港查询详情")
setBackArrow(if (DeviceUtil.isPhone()) "进港货物" else "国际进港查询详情")
binding.viewModel = viewModel
// 初始化ViewModel(传入maWbId)