feat: 完成ULD管理页面5.5寸手机端适配

- 手机版列表(三色状态标签卡片 + 筛选弹层 + 浮动新增 + 全选/批量删除)、
  一套 activity_uld_edit 手机布局按 pageType 覆盖 ULD 新增/修改/详情三态
  (详情右上铅笔进修改、状态底部选择面板、所在港默认 HFE、手机端必填校验);
  平板布局迁至 layout-sw600dp,Kotlin 双端共用,平板端实机回归零变化
- 新增公共组件 PhoneFormRow(行式表单,INPUT/SELECT/DATE/TEXT 四形态,
  SELECT 内置底部选择面板);PhoneBottomBar 增加 actionDanger 危险按钮样式;
  新增 FAB/danger按钮/浅红标签/垃圾桶/铅笔等资源
- ULDBean 补解析接口既有出参 ifNo/efNo/checkInDate/checkOutDate 并预留 source;
  批量删除以队列串行调用单条 deleteUld 实现
- 手机首页「国际」Tab 接入 ULD管理入口(ARouter + ComprehensiveUld 权限),
  登录→菜单→页面全链路实机验证通过,方向无闪屏,crash=0
- 后端缺口 5 项(状态三态、来源字段、筛选入参、批量删除接口、字段语义)
  登记《后端接口对接问题清单.xlsx》#7~#11;skill 沉淀本次踩坑
  (FAB elevation 盖弹层、Spinner 异步回调竞态、登录哈希回填)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-29 16:30:42 +08:00
parent bbc29ca2e1
commit 5a019a55c4
33 changed files with 1848 additions and 422 deletions

View File

@@ -55,8 +55,12 @@ python3 $S/design_shots.py --html "…/出库交接.html" --out /tmp/design \
- **已有字段** → 直接复用(如出港移库的 Tab 直接绑既有 `moveState`
- **平板没有的新维度**(新 Tab 状态、新下拉、新排序)→ **先查 api-doc MCP 拿权威参数名**
流程见 `references/api-doc.md`(连接方式 + 5 个工具 + 逐接口核对清单)
文档里查不到、或业务语义拿不准(如数据源该用哪个 `DictUtils` 方法)才用 `AskUserQuestion` 问用户
流程见 `references/api-doc.md`(连接方式 + 5 个工具 + 逐接口核对清单)
**最高决策规则(用户 2026-07-29 拍板,此后不再逐次询问):业务改动完全以设计稿为准,不做妥协。**
接口不支持设计稿的某个维度时UI 照设计稿完整实现(绑预留字段/占位,传参后端静默忽略无副作用),
缺口直接登记 `documents/后端接口对接问题清单.xlsx` 提修改需求,后端补齐后前端自动生效。
仅当设计稿本身歧义label 无法推断字段语义)才用 `AskUserQuestion` 问用户。
这一步不能猜,也**不要拿「实测不生效」当结论**。出库交接第一版猜了 `hoState`,实测两个 Tab
返回同一批数据,一度误判为「后端不支持」;后查 api-doc 才发现正确参数名是 `handoverState`——

View File

@@ -65,6 +65,11 @@ curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \
- `IntExpMove`:出参无航班字段(缺口 #1)、无操作人姓名(缺口 #2`opId`/`opdate`/`businessType`
文档有定义但实测恒 null缺口 #3`pageQueryTotal` 正常(与 pageQuery 口径一致,`moveState` 过滤生效)
- `typeCode/getSpecialCodeByParam``flag=1` 国际,`ieFlag` 必须传空串(传 `"E"` 返回空数组)
- `eqm/uld`ULD信息6 个端点):查询入参仅 `uld`/`status`/`uldSuffix`uldSuffix 名义是
"uld后两位",实际就是**按所属航司筛选**,配 `DictUtils.getIntCarrierList``status` 仅两态
0 正常/1 故障(三态需求=缺口 #7);无「来源」字段(#8)、无 `checkInDate`/`ifNo` 筛选入参(#9)、
无批量删除(#10`deleteUld``@Query` 单条);出参 `ifNo`/`efNo`/`checkInDate`/`checkOutDate`
文档无描述,按命名推断进/出港航班号与出入库时间(#11 待确认)
## 内网直调验证技巧(比驱动 UI 快得多)

View File

@@ -17,6 +17,18 @@
| `PhoneBottomBar` | 底部操作条(全选 + 已选统计 + 主按钮) | `allChecked``countText``actionText``setOnAllCheckClick``setOnActionClick` |
| `PhoneStatBox` | 卡片内 2~4 列统计框,未传 label 的列自动隐藏 | `label1..4``value1..4` |
| `PhoneKvItem` | 详情页字段项(灰标签 + 数值) | `title``value``tag`(true → 橙色高亮标签) |
| `PhoneFormRow` | 行式表单项(左标签 minWidth 110dp + 右值 + 1px 分隔线),覆盖新增/修改/详情三态表单 | `title``hint``type`(`PhoneFormRowType.INPUT`/`SELECT`/`DATE`/`TEXT`)、`value`(双向)、`list`(SELECT 选项)、`required``enable``numeric``setRefreshCallBack` |
`PhoneFormRow` 要点SELECT 内置 XPopup 底部选择面板点击整行弹出无需页面代码TEXT 为只读右对齐、
空值自动占位 "--"详情态type 用三元按 `pageType` 切换即可一套布局覆盖三态页面(参考
`app/res/layout/activity_uld_edit.xml`)。`PhoneBottomBar``actionDanger="@{true}"` 切浅红删除按钮。
⚠️ 两个已踩坑:
- **FAB 盖住弹层**:浮动按钮带 elevation 时会浮在 `PhoneFilterPanel` 之上,弹层实例要加
`android:elevation="8dp"`> FAB 的 6dp
- **Spinner 选择回调是异步的**`onItemSelected` 由系统 post自动化测试里 tap 选项后立即 tap「确认」
可能抢在回值之前发出请求(表现为 UI 已显示选中但请求参数为 null——脚本里选完要 `sleep 1` 以上;
真人操作间隔足够,不受影响
`KeyValue``dev.utils.app.info.KeyValue`,字段是 **`key`(显示文案)+ `value`(业务值)**
不是 `name``PhoneStatusTab``tabs` 就按 `KeyValue("待交接","0")` 传。

View File

@@ -46,8 +46,19 @@ adb -s <serial> install -r -d app/build/outputs/apk/debug/app-debug.apk
adb -s <serial> shell monkey -p com.lukouguoji.aerologic -c android.intent.category.LAUNCHER 1
```
登录页账号密码需要用户提供。填表用 `input text`,注意 `#` 等字符要转义(`Aa123456\#`
底部有「首页 / 国内 / 国际 / 我的」Tab国际业务页找对应入口。
测试环境账号在记忆文件 `test-env-login.md`ADMIN / 用户已授权保存),可自主登录
填表用 `input text`**`#` 不需要转义**——新版 adb 的 input text 参数不经远端 shell 解析,
`\#` 反而会把 `\` 也输进去(实测多出一位)。
⚠️ **「记住密码」回填哈希坑(实测踩过)**:输入用户名后 App 会调 `queryUserByName`
把本地存储的 **bcrypt 哈希**回填进密码框,盖掉/混入你输入的明文 → 登录 200 但校验失败、
静默停在登录页(密码框点数对不上是判断信号:明文 9 位 vs 回填后 10 位显示)。
正确顺序:点密码框 → 等回填sleep 1`input keycombination 113 29`CTRL+A+
`KEYCODE_DEL` 清空 → 再输明文 → `KEYCODE_BACK` 收键盘 → 点登录。
键盘不收起时「登录」按钮可能点不到tap 被吞),收起后再点。
底部有「首页 / 国内 / 国际 / 我的」Tab国际业务页找对应入口
(底部 Tab 的「国际」与顶部筛选的「国际」同名,`tap-text "国际" 2` 指定第 2 处)。
**首页菜单是按权限过滤的**:当前账号角色没有该权限时,入口根本不显示(本次 ADMIN 登录后
国际业务只有「板箱过磅」「进港理货」,没有「出库交接」)。这时走下面的直启。

View File

@@ -7,6 +7,20 @@
## [Unreleased]
### 新增 (Added)
- 「ULD管理」5.5 寸手机端适配app 模块首个适配页):列表卡片(三色状态标签)+ 筛选弹层(入库时间/进港航班号/所属航司/来源)+
右下角浮动新增 + 底部全选/批量删除(循环调用单条删除接口)+ 一套 `activity_uld_edit` 手机布局覆盖 新增/修改/详情 三态
(详情态右上铅笔进入修改、状态底部选择面板、所在港默认 HFE、必填校验仅手机生效
- 新增手机版公共组件 `PhoneFormRow`行式表单项INPUT/SELECT/DATE/TEXT 四形态SELECT 内置底部选择面板);
`PhoneBottomBar` 增加 `actionDanger` 危险按钮样式;新增 `bg_phone_fab``bg_phone_btn_danger``bg_phone_tag_red_light`
`ic_phone_trash``ic_phone_edit` 等资源
- `ULDBean` 补解析接口既有出参 `ifNo`/`efNo`/`checkInDate`/`checkOutDate` 并预留 `source`;后端缺口 5 项
(状态三态、来源字段、筛选入参、批量删除接口、字段语义)登记问题清单 #7~#11
### 验证 (Verified)
- ULD管理双端实机验证通过手机端列表/筛选/详情/修改/新增/单选全选/批删确认全链路 crash=0、方向无闪屏
平板端列表与详情回归无变化
### 修复 (Fixed)
- 出库交接手机版「待/已交接」Tab 与角标计数的过滤参数名修正:`hoState``handoverState`
(以 api-doc 接口文档为准;此前误传 `hoState` 被后端静默忽略,两个 Tab 返回同一批数据)。

View File

@@ -1049,6 +1049,14 @@ DataBinding 适配器统一放在 `PhoneWidgetKtx.kt`(同名属性按控件类
| `PhoneBottomBar` | 底部操作条:全选 + 已选统计 + 主按钮 | `allChecked``countText``actionText``setOnAllCheckClick``setOnActionClick` |
| `PhoneStatBox` | 卡片内 2~4 列统计框(未传 label 的列自动隐藏) | `label1..4``value1..4` |
| `PhoneKvItem` | 详情页字段项(灰标签 + 数值),`tag=true` 转橙色高亮 | `title``value``tag` |
| `PhoneFormRow` | 行式表单项(左标签+右值+分隔线),`PhoneFormRowType` = `INPUT`/`SELECT`(内置底部选择面板)/`DATE`/`TEXT`(只读右对齐,空值 "--") | `title``hint``type``value`(双向)、`list``required``enable``numeric``setRefreshCallBack` |
`PhoneBottomBar` 追加 `actionDanger` 属性true 时主按钮转浅红底红字 + 垃圾桶图标ULD 管理批量删除)。
新增资源:`bg_phone_btn_danger``bg_phone_fab`(圆形浮动 + 按钮)、`bg_phone_tag_red_light`(浅红标签)、
`ic_phone_trash``ic_phone_edit`、色值 `phone_danger_bg/text`
⚠️ **弹层与浮动按钮的层级**`PhoneFilterPanel` 默认无 elevation页面里有带 elevation 的浮动按钮FAB
会穿透到弹层之上——给弹层实例加 `android:elevation="8dp"`(大于 FAB 的 6dp
**`PhoneFilterPanel` 自带内容插槽**:把 `PhoneDataLayout` 直接写在其标签内即可,组件会自动移入面板中部
并施加 20dp 项间距,无需关心内部层级:
@@ -1092,6 +1100,8 @@ override fun dispatchRestoreInstanceState(container: SparseArray<Parcelable>) =
- 「国际出港移库」`IntExpMoveActivity` + 「运单详情」`IntExpMoveDetailActivity`(框架参考页)
- 「国际出港出库交接」`IntExpOutHandoverActivity` + 「板箱详情」`IntExpOutHandoverDetailActivity`
(公共组件首个完整落地页,双端实机验证通过)
- 「ULD管理」`UldListActivity` + `UldEditActivity`app 模块首个适配页;一套编辑布局覆盖
新增/修改/详情三态;批量删除为前端循环调用单条接口;状态三态/来源等 5 项后端缺口见问题清单 #7~#11
-**待办**
- `PhoneSearchBar` 接入 AutoQuery 联想(`AutoQueryManager` 目前只对接了 Pad 系组件)
- 出库交接 Tab 角标恒 0`IntExpOutHandover/pageQueryTotal` 出参恒 0后端缺陷问题清单 #6

View File

@@ -38,5 +38,17 @@
android:exported="true"
tools:replace="android:exported" />
<!-- ULD管理手机版适配验证页 -->
<activity
android:name="com.lukouguoji.aerologic.page.uld.list.UldListActivity"
android:exported="true"
tools:replace="android:exported" />
<!-- ULD新增/修改/详情(手机版适配验证页) -->
<activity
android:name="com.lukouguoji.aerologic.page.uld.edit.UldEditActivity"
android:exported="true"
tools:replace="android:exported" />
</application>
</manifest>

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
@@ -33,6 +34,25 @@ class UldEditViewModel : BaseViewModel() {
// 所属航司下拉列表数据源POST /typeCode/intCarrier
val carrierList = MutableLiveData<List<KeyValue>>(emptyList())
// ========== 手机版5.5 寸手持端)专用 ==========
/** 来源选项(本地枚举;后端字段暂不支持,需求已登记 documents/后端接口对接问题清单.xlsx */
val sourceEditList = MutableLiveData<List<KeyValue>>(
listOf(
KeyValue("空运", "空运"),
KeyValue("陆运", "陆运"),
)
)
/**
* 手机版状态选项。设计稿为三态(可用/占用/维修),后端枚举当前仅 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)
@@ -42,11 +62,20 @@ class UldEditViewModel : BaseViewModel() {
if (id.isEmpty()) {
// 新增:直接加载航司列表
loadCarrierList(null)
// 手机版新增默认所在港 HFE设计稿约定平板无此预填行为不变
if (DeviceUtil.isPhone()) {
uldBean.value = uldBean.value?.copy(airport = "HFE")
}
} else {
getData()
}
}
/** 手机版状态行选中回调copy 重新赋值以触发标签样式刷新) */
fun onStatusSelected(statusValue: String) {
uldBean.value = uldBean.value?.copy(status = statusValue)
}
private fun getData() {
if (id.isEmpty()) return
launchLoadingCollect({
@@ -72,6 +101,17 @@ class UldEditViewModel : BaseViewModel() {
showToast("ULD编号不能为空")
return
}
// 手机版按设计稿校验必填项(自重 / 入库时间);平板表单无入库时间项,保持原校验行为
if (DeviceUtil.isPhone()) {
if (bean.uldWeight.isBlank()) {
showToast("自重不能为空")
return
}
if (bean.checkInDate.isBlank()) {
showToast("入库时间不能为空")
return
}
}
val isAdd = pageType.value == DetailsPageType.Add
launchLoadingCollect({
if (isAdd) NetApply.api.saveUld(bean.toRequestBody())
@@ -79,7 +119,12 @@ class UldEditViewModel : BaseViewModel() {
}) {
onSuccess = {
showToast(it.msg.noNull(if (isAdd) "新增成功" else "修改成功"))
if (isAdd) uldBean.value = ULDBean() else getData()
if (isAdd) {
// 清空表单继续录入;手机版保持所在港默认 HFE与进入页面时一致
uldBean.value = if (DeviceUtil.isPhone()) ULDBean(airport = "HFE") else ULDBean()
} else {
getData()
}
}
}
}

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,46 @@ class UldListActivity : BaseBindingActivity<ActivityUldListBinding, UldListViewM
viewModel.refresh()
}
// ==================== 手机版专用交互(纯 UI复用既有 ViewModel 字段) ====================
/** 手机版筛选弹层显隐切换 */
fun toggleFilterPanel() {
filterPanelVisible.set(!filterPanelVisible.get())
}
/**
* 手机版筛选:重置
*
* 只清空弹层内的四个条件(入库时间 / 进港航班号 / 所属航司 / 来源),不影响顶部搜索框。
*/
fun resetFilter() {
viewModel.checkInDateFilter.value = ""
viewModel.ifNoFilter.value = ""
viewModel.uldSuffix.value = ""
viewModel.sourceFilter.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。
*
* 平板 / 手机共用:布局按资源限定符切换,本类不做设备判断。
* 平板独有 idtv_modify / tv_delete 侧滑按钮)与手机独有 idiv_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,27 @@ class UldListViewModel : BasePageViewModel() {
val uldSuffix = MutableLiveData("")
val uldNo = MutableLiveData("")
// ========== 手机版5.5 寸手持端)专用筛选条件 ==========
// 平板布局无对应控件,恒为空 → 不进请求参数,平板查询行为与改造前完全一致。
// 三个入参后端暂不支持api-doc 已核对),已登记 documents/后端接口对接问题清单.xlsx
// 按「以设计为准」的约定照传(后端静默忽略无副作用),后端支持后自动生效。
val checkInDateFilter = MutableLiveData("") // 入库时间
val ifNoFilter = MutableLiveData("") // 进港航班号
val sourceFilter = MutableLiveData("") // 来源:空运 / 陆运
/** 来源下拉(本地枚举,后端字段需求已登记清单) */
val sourceList = MutableLiveData<List<KeyValue>>(
listOf(
KeyValue("全部", ""),
KeyValue("空运", "空运"),
KeyValue("陆运", "陆运"),
)
)
// ========== 手机版批量选择状态 ==========
val isAllChecked = MutableLiveData(false)
val selectedCount = MutableLiveData("0")
// 状态下拉列表
val statusList = MutableLiveData<List<KeyValue>>(
listOf(
@@ -61,16 +82,75 @@ class UldListViewModel : BasePageViewModel() {
"status" to status.value?.ifEmpty { null },
"uldSuffix" to uldSuffix.value?.ifEmpty { null },
"uld" to uldNo.value?.ifEmpty { null },
// 手机版筛选维度(平板恒空不参与);后端暂不支持这三个入参,已登记清单
"checkInDate" to checkInDateFilter.value?.ifEmpty { null },
"ifNo" to ifNoFilter.value?.ifEmpty { null },
"source" to sourceFilter.value?.ifEmpty { null },
).toRequestBody()
)
}) {
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/deleteUld批量接口需求已登记清单
* 此处按队列逐条串行调用,全部完成后统一刷新;中途失败即停并提示。
*/
fun deleteSelected() {
val ulds = getSelectedItems().map { it.uld }
if (ulds.isEmpty()) {
showToast("请选择要删除的ULD")
return
}
deleteQueue(ulds, 0)
}
private fun deleteQueue(ulds: List<String>, index: Int) {
if (index >= ulds.size) {
showToast("已删除 ${ulds.size}")
refresh()
return
}
launchLoadingCollect({ NetApply.api.deleteUld(ulds[index]) }) {
onSuccess = { deleteQueue(ulds, index + 1) }
onFailed = { _, msg ->
showToast("删除 ${ulds[index]} 失败:${msg.noNull("未知错误")}")
refresh()
}
}
}
fun onUldScanClick() {
ScanModel.startScan(DevUtils.getTopActivity(), Constant.RequestCode.ULD)
}

View File

@@ -0,0 +1,171 @@
<?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>
<!-- 备注(全行,多行输入) -->
<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,254 @@
<?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.5"
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="@{3}" />
<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.5"
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="3.6"
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.remark}"
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

@@ -1,167 +1,267 @@
<?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.xmlPadDataLayoutNew 三列表单),
两者是同一布局的资源变体DataBinding 生成同一个 ActivityUldEditBinding 类。
变体之间必须满足:
· DataBinding 变量完全一致viewModel / activity
→ UldEditViewModel 的加载/保存逻辑全部复用,平板端行为不受影响
一套布局覆盖设计稿三个页面(标题由 Activity 按 pageType 设置):
· ULD新增Add :可编辑 + 底部保存;所在港默认 HFE、必填星编号/自重/入库时间)
· ULD修改Modify编号只读其余可编辑 + 底部保存
· ULD详情Details全只读右对齐 + 顶栏右侧铅笔进入修改 + 额外展示最大装载容积/最大载重
「来源」「状态三态(占用)」为后端暂不支持的设计稿要求,
已登记 documents/后端接口对接问题清单.xlsxUI 先行、后端补齐后自动生效。
-->
<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 : (viewModel.uldBean.isStatusOccupied ? @drawable/bg_phone_tag_orange : @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 : (viewModel.uldBean.isStatusOccupied ? @color/phone_tag_orange_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>
<!-- 备注(全行,多行输入) -->
<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='@{"请选择来源"}'
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"
android:layout_height="wrap_content"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入重"}'
numeric="@{true}"
required="@{viewModel.pageType == DetailsPageType.Add}"
title='@{"自重(kg)"}'
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.INPUT}"
value="@={viewModel.uldBean.uldWeight}" />
<!-- 最大装载容积(仅详情展示,与设计稿一致) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
title='@{"最大装载容积(m³)"}'
type="@{PhoneFormRowType.TEXT}"
value="@{viewModel.uldBean.maxVolume}"
android:visibility="@{viewModel.pageType == DetailsPageType.Details ? View.VISIBLE : View.GONE}" />
<!-- 最大载重(仅详情展示,与设计稿一致) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
title='@{"最大载重(kg)"}'
type="@{PhoneFormRowType.TEXT}"
value="@{viewModel.uldBean.maxWeight}"
android:visibility="@{viewModel.pageType == DetailsPageType.Details ? View.VISIBLE : View.GONE}" />
<!-- 进港航班号(绑 ifNo语义待后端确认已登记清单 -->
<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.ifNo}" />
<!-- 所在港(新增默认 HFE由 ViewModel 手机开关预填) -->
<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.airport}" />
<!-- 入库时间(绑 checkInDate筛选/格式语义待后端确认,已登记清单) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入入库时间"}'
required="@{viewModel.pageType == DetailsPageType.Add}"
title='@{"入库时间"}'
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.DATE}"
value="@={viewModel.uldBean.checkInDate}" />
<!-- 备注 -->
<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,175 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
ULD管理 —— 手机版布局5.5 寸手持端,最小宽度 < 600dp 时生效)
平板版为同名文件 layout-sw600dp/activity_uld_list.xml两者是同一布局的资源变体
DataBinding 因此生成同一个 ActivityUldListBinding 类。
变体之间必须满足:
· DataBinding 变量完全一致viewModel / activity
· 保留 Activity 中引用的控件 idsrl / 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='@{"筛选条件"}'>
<!-- 入库时间(后端筛选入参暂不支持,已登记清单) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请输入入库时间"}'
title='@{"入库时间"}'
type="@{PhoneDataLayoutType.DATE}"
value="@={viewModel.checkInDateFilter}" />
<!-- 进港航班号(后端筛选入参暂不支持,已登记清单) -->
<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.ifNoFilter}" />
<!-- 所属航司(后端入参 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.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择来源"}'
list="@{viewModel.sourceList}"
title='@{"来源"}'
type="@{PhoneDataLayoutType.SPINNER}"
value="@={viewModel.sourceFilter}" />
</com.lukouguoji.module_base.ui.weight.phone.PhoneFilterPanel>
</FrameLayout>
</layout>

View File

@@ -1,254 +1,148 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
ULD管理 —— 列表项手机版布局5.5 寸手持端,最小宽度 < 600dp 时生效)
平板版为同名文件 layout-sw600dp/item_uld_list.xmlSwipeMenuLayout 侧滑修改/删除),
两者是同一布局的资源变体DataBinding 生成同一个 ItemUldListBinding 类。
变体之间必须满足:
· DataBinding 变量完全一致bean
· 保留 ViewHolder / ViewModel 引用的 idll_content点卡片进详情复用平板 onItemClick 链路)
· 平板独有 idtv_modify / tv_delete / iv_icon与手机独有 idiv_check
在 Binding 基类中自动为 @NullableViewHolder 判空使用
状态标签三色(设计稿):可用=浅绿 / 占用=浅橙 / 维修=浅红。
后端当前仅两态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.5"
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="@{3}" />
<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.5"
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="3.6"
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.remark}"
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 : (bean.isStatusOccupied ? @drawable/bg_phone_tag_orange : @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 : (bean.isStatusOccupied ? @color/phone_tag_orange_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">
<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.checkInDate.empty ? "-" : bean.checkInDate)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp" />
</LinearLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
</layout>

View File

@@ -19,6 +19,18 @@ data class ULDBean(
var status: String = "",
// 备注
var remark: String = "",
// ========== 以下字段接口出参已有api-doc /eqm/uld/pageQuery此前 Bean 未解析 ==========
// 进港航班号(语义待后端确认,见 documents/后端接口对接问题清单.xlsx
var ifNo: String = "",
// 出港航班号
var efNo: String = "",
// 入库时间
var checkInDate: String = "",
// 出库时间
var checkOutDate: String = "",
// ========== 后端暂无对应字段,前端按设计稿预留(提交后端忽略,无副作用) ==========
// 来源:空运 / 陆运(后端字段需求已登记清单)
var source: String = "",
){
val checked = ObservableBoolean(false)
@@ -27,4 +39,23 @@ data class ULDBean(
"1" -> "故障"
else -> status
}
// ========== 手机版5.5 寸手持端)三态状态展示 ==========
// 设计稿状态为 可用(绿)/占用(橙)/维修(红) 三态后端当前仅两态0/1
// 按语义映射 0→可用、1→维修"2"→占用为后端扩展枚举后的预留(需求已登记清单)。
/** 手机版状态文案 */
val statusPhoneName: String
get() = when (status) {
"0" -> "可用"
"1" -> "维修"
"2" -> "占用"
else -> statusName()
}
/** 可用(绿色标签) */
val isStatusAvailable: Boolean get() = status == "0"
/** 占用(橙色标签,后端扩展枚举后的预留) */
val isStatusOccupied: Boolean get() = status == "2"
}

View File

@@ -144,6 +144,8 @@ object ARouterConstants {
const val ACTIVITY_URL_INT_EXP_MOVE = "/gjc/IntExpMoveActivity" //国际出港 出港移库
const val ACTIVITY_URL_GJC_ASSEMBLE_ALLOCATE = "/gjc/GjcAssembleAllocateActivity" //国际出港 组装分配
const val ACTIVITY_URL_INT_EXP_OUT_HANDOVER = "/gjc/IntExpOutHandoverActivity" //国际出港 出库交接
const val ACTIVITY_URL_ULD_LIST = "/app/UldListActivity" //综合管理 ULD管理手机端首页入口用
const val ACTIVITY_URL_INT_EXP_LOAD = "/gjc/IntExpLoadActivity" //国际出港 出港装载
const val ACTIVITY_URL_INT_EXP_TALLY = "/gjc/IntExpTallyActivity" //国际出港 出港理货
const val ACTIVITY_URL_INT_EXP_ARRIVE = "/gjc/IntExpArriveActivity" //国际出港 出港运抵

View File

@@ -64,6 +64,29 @@ class PhoneBottomBar @JvmOverloads constructor(
tvAction.text = v
}
/**
* 危险操作样式:浅红底 + 红字 + 垃圾桶图标(如 ULD 管理的批量删除)。
* 默认 false 为主色实底按钮,既有页面不受影响。
*/
var actionDanger: Boolean = false
set(v) {
field = v
if (v) {
tvAction.setBackgroundResource(R.drawable.bg_phone_btn_danger)
tvAction.setTextColor(ContextCompat.getColor(context, R.color.phone_danger_text))
val icon = ContextCompat.getDrawable(context, R.drawable.ic_phone_trash)?.apply {
val size = (16 * resources.displayMetrics.density).toInt()
setBounds(0, 0, size, size)
}
tvAction.setCompoundDrawables(icon, null, null, null)
tvAction.compoundDrawablePadding = (4 * resources.displayMetrics.density).toInt()
} else {
tvAction.setBackgroundResource(R.drawable.bg_phone_btn_primary)
tvAction.setTextColor(ContextCompat.getColor(context, R.color.white))
tvAction.setCompoundDrawables(null, null, null, null)
}
}
init {
orientation = HORIZONTAL
gravity = Gravity.CENTER_VERTICAL

View File

@@ -0,0 +1,232 @@
package com.lukouguoji.module_base.ui.weight.phone
import android.content.Context
import android.os.Parcelable
import android.text.InputType
import android.util.AttributeSet
import android.util.SparseArray
import android.view.Gravity
import android.view.View
import android.widget.EditText
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.widget.doOnTextChanged
import androidx.databinding.InverseBindingListener
import com.lukouguoji.module_base.R
import com.lukouguoji.module_base.ktx.formatDate
import com.lukouguoji.module_base.ktx.getActivity
import com.lukouguoji.module_base.util.Common
import com.lxj.xpopup.XPopup
import dev.utils.app.info.KeyValue
import java.util.Calendar
/**
* 手机版行式表单项5.5 寸手持端公共组件)
*
* 结构:左标签(固定 110dp+ 必填星)+ 右值区 + 可选箭头 + 底部 1px 分隔线。
* 对应设计稿中新增 / 修改 / 详情三态共用的行式表单(如 01_ULD管理
* 与 [PhoneDataLayout](上下结构,用于筛选弹层)互补,形态见 [PhoneFormRowType]。
*
* XML 用法type 按页面状态用三元切换即可覆盖三态页面):
* ```xml
* <com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
* android:layout_width="match_parent"
* android:layout_height="wrap_content"
* title='@{"所属航司"}'
* hint='@{"请选择所属航司"}'
* list="@{viewModel.carrierList}"
* type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.SELECT}"
* value="@={viewModel.uldBean.carrier}" />
* ```
*/
class PhoneFormRow @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
val tvTitle: TextView
val tvMust: TextView
val et: EditText
val tv: TextView
val ivArrow: ImageView
val llRow: LinearLayout
/** 双向绑定回调 */
var onChangeListener: InverseBindingListener? = null
/** 选择 / 日期确定后的回调 */
var refreshCallBack: (() -> Unit)? = null
var type: PhoneFormRowType = PhoneFormRowType.INPUT
set(v) {
field = v
applyType()
applyValue()
}
var title: String = ""
set(v) {
field = v
tvTitle.text = v
}
var hint: String = ""
set(v) {
field = v
et.hint = v
tv.hint = v
}
var value: String = ""
set(v) {
if (field == v) return
field = v
applyValue()
onChangeListener?.onChange()
}
/** SELECT 形态的选项key 显示文案 / value 业务值) */
var list: List<KeyValue> = emptyList()
set(v) {
field = v
applyValue()
}
var required: Boolean = false
set(v) {
field = v
tvMust.visibility = if (v) VISIBLE else GONE
}
var enable: Boolean = true
set(v) {
field = v
et.isEnabled = v
applyType()
}
/** INPUT 形态是否数字键盘(自重等数值项) */
var numeric: Boolean = false
set(v) {
field = v
et.inputType = if (v) {
InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
} else {
InputType.TYPE_CLASS_TEXT
}
}
init {
orientation = VERTICAL
inflate(context, R.layout.layout_phone_form_row, this)
llRow = findViewById(R.id.ll_row)
tvTitle = findViewById(R.id.tv_title)
tvMust = findViewById(R.id.tv_must)
et = findViewById(R.id.et)
tv = findViewById(R.id.tv)
ivArrow = findViewById(R.id.iv_arrow)
et.doOnTextChanged { text, _, _, _ ->
// 仅 INPUT 形态才回写,避免隐藏的 EditText 被系统状态恢复时误清空值
if (type == PhoneFormRowType.INPUT) {
value = text.toString()
}
}
applyType()
}
private val selectClick: (v: View) -> Unit = {
if (enable && list.isNotEmpty()) {
XPopup.Builder(context)
.asBottomList(hint.ifEmpty { title }, list.map { it.key }.toTypedArray()) { position, _ ->
value = list.getOrNull(position)?.value ?: ""
refreshCallBack?.invoke()
}
.show()
}
}
private val dateClick: (v: View) -> Unit = {
if (enable) {
Common.onYearMonthDay(context.getActivity(), value) { year, month, day ->
val calendar = Calendar.getInstance()
calendar.set(year, month - 1, day)
value = calendar.time.formatDate()
refreshCallBack?.invoke()
}
}
}
private fun applyType() {
when (type) {
PhoneFormRowType.INPUT -> {
et.visibility = VISIBLE
tv.visibility = GONE
ivArrow.visibility = GONE
llRow.setOnClickListener(null)
llRow.isClickable = false
}
PhoneFormRowType.SELECT -> {
et.visibility = GONE
tv.visibility = VISIBLE
tv.gravity = Gravity.START or Gravity.CENTER_VERTICAL
ivArrow.visibility = if (enable) VISIBLE else GONE
llRow.setOnClickListener(selectClick)
}
PhoneFormRowType.DATE -> {
et.visibility = GONE
tv.visibility = VISIBLE
tv.gravity = Gravity.START or Gravity.CENTER_VERTICAL
ivArrow.visibility = GONE
llRow.setOnClickListener(dateClick)
}
PhoneFormRowType.TEXT -> {
et.visibility = GONE
tv.visibility = VISIBLE
tv.gravity = Gravity.END or Gravity.CENTER_VERTICAL
tv.hint = ""
ivArrow.visibility = GONE
llRow.setOnClickListener(null)
llRow.isClickable = false
}
}
}
private fun applyValue() {
when (type) {
PhoneFormRowType.INPUT -> {
if (et.text.toString() != value) et.setText(value)
}
PhoneFormRowType.SELECT -> {
// 显示选中项的文案;列表里找不到就按原值显示(如后端返回的历史值)
tv.text = list.firstOrNull { it.value == value }?.key ?: value
}
PhoneFormRowType.DATE -> {
tv.text = value
}
PhoneFormRowType.TEXT -> {
// 只读展示:空值统一占位 "--"(与设计稿一致)
tv.text = value.ifEmpty { "--" }
}
}
}
/** 只保存/恢复自身状态,避免内部子控件 id 与其他实例串档(公共组件必做,见 components.md */
override fun dispatchSaveInstanceState(container: SparseArray<Parcelable>) {
dispatchFreezeSelfOnly(container)
}
override fun dispatchRestoreInstanceState(container: SparseArray<Parcelable>) {
dispatchThawSelfOnly(container)
}
}

View File

@@ -0,0 +1,18 @@
package com.lukouguoji.module_base.ui.weight.phone
/**
* [PhoneFormRow] 的形态。
*
* | 形态 | 值区控件 | 交互 |
* |----------|--------------------|------|
* | `INPUT` | EditText左对齐 | 直接输入 |
* | `SELECT` | TextView + 右箭头 | 点击弹底部选择面板list 提供选项) |
* | `DATE` | TextView | 点击弹日历 |
* | `TEXT` | TextView右对齐 | 只读展示(详情态) |
*/
enum class PhoneFormRowType {
INPUT,
SELECT,
DATE,
TEXT,
}

View File

@@ -226,3 +226,58 @@ fun setPhoneKvItemAttrs(item: PhoneKvItem, title: String?, value: String?, tag:
tag?.let { item.tag = it }
item.value = value.orEmpty()
}
///////////////////////////////////////////////////////////////////////////
// PhoneFormRow
///////////////////////////////////////////////////////////////////////////
@BindingAdapter("title", "hint", "type", "required", "enable", "numeric", requireAll = false)
fun setPhoneFormRowAttrs(
row: PhoneFormRow,
title: String?,
hint: String?,
type: PhoneFormRowType?,
required: Boolean?,
enable: Boolean?,
numeric: Boolean?
) {
// type 先于其余属性生效,确保 value/hint 写进正确的子控件
type?.let { row.type = it }
title?.let { row.title = it }
hint?.let { row.hint = it }
required?.let { row.required = it }
enable?.let { row.enable = it }
numeric?.let { row.numeric = it }
}
@BindingAdapter("value", requireAll = false)
fun setPhoneFormRowValue(row: PhoneFormRow, value: String?) {
if (row.value != value.orEmpty()) row.value = value.orEmpty()
}
@InverseBindingAdapter(attribute = "value", event = "valueAttrChanged")
fun getPhoneFormRowValue(row: PhoneFormRow): String = row.value
@BindingAdapter("valueAttrChanged", requireAll = false)
fun setPhoneFormRowValueAttrChanged(row: PhoneFormRow, listener: InverseBindingListener) {
row.onChangeListener = listener
}
@BindingAdapter("list", requireAll = false)
fun setPhoneFormRowList(row: PhoneFormRow, list: List<KeyValue>?) {
row.list = list ?: emptyList()
}
@BindingAdapter("setRefreshCallBack", requireAll = false)
fun setPhoneFormRowRefreshCallBack(row: PhoneFormRow, callBack: (() -> Unit)?) {
row.refreshCallBack = callBack
}
///////////////////////////////////////////////////////////////////////////
// PhoneBottomBar追加危险操作样式
///////////////////////////////////////////////////////////////////////////
@BindingAdapter("actionDanger", requireAll = false)
fun setPhoneBottomBarActionDanger(bar: PhoneBottomBar, danger: Boolean?) {
danger?.let { bar.actionDanger = it }
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 手机版危险操作按钮:浅红底 + 10dp 圆角(如 ULD 管理的批量删除) -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#FECACA" />
<corners android:radius="10dp" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="@color/phone_danger_bg" />
<corners android:radius="10dp" />
</shape>
</item>
</selector>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 手机版右下角浮动新增按钮:主色圆形 -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="oval">
<solid android:color="#1D4FD8" />
</shape>
</item>
<item>
<shape android:shape="oval">
<solid android:color="@color/phone_primary" />
</shape>
</item>
</selector>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 手机版状态标签浅红底红字ULD管理「维修」态配文字色 phone_danger_text -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/phone_danger_bg" />
<corners android:radius="6dp" />
</shape>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 手机版编辑铅笔图标MDI pencil可 tint 染色 -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFF"
android:pathData="M20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18,2.9 17.35,2.9 16.96,3.29L15.12,5.12L18.87,8.87M3,17.25V21H6.75L17.81,9.93L14.06,6.18L3,17.25Z" />
</vector>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 手机版删除图标MDI delete-outline可 tint 染色 -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/phone_danger_text"
android:pathData="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z" />
</vector>

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
PhoneFormRow 内部布局(手机版行式表单项)
结构:左标签(+必填星)+ 右值区(输入 / 只读文本互斥显示)+ 可选箭头 + 底部分隔线
对应设计稿01_ULD管理 的新增 / 修改 / 详情三个表单页的行式布局
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:parentTag="android.widget.LinearLayout">
<LinearLayout
android:id="@+id/ll_row"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="54dp"
android:orientation="horizontal">
<!-- 左标签 + 必填星minWidth 保证编辑态值列对齐,长标签自适应不折行) -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minWidth="110dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/phone_text_label"
android:textSize="15sp" />
<TextView
android:id="@+id/tv_must"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:text="*"
android:textColor="@color/phone_danger_text"
android:textSize="15sp"
android:visibility="gone" />
</LinearLayout>
<!-- 值区:输入 -->
<EditText
android:id="@+id/et"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:inputType="text"
android:maxLines="1"
android:paddingVertical="15dp"
android:textColor="@color/phone_text_title"
android:textColorHint="@color/phone_text_hint"
android:textSize="15sp" />
<!-- 值区:只读 / 选择 / 日期文本 -->
<TextView
android:id="@+id/tv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:paddingVertical="16dp"
android:textColor="@color/phone_text_title"
android:textColorHint="@color/phone_text_hint"
android:textSize="15sp"
android:visibility="gone" />
<!-- SELECT 态右箭头 -->
<ImageView
android:id="@+id/iv_arrow"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="6dp"
android:src="@drawable/ic_phone_chevron_right"
android:visibility="gone" />
</LinearLayout>
<View
android:id="@+id/v_divider"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/phone_divider" />
</merge>

View File

@@ -73,5 +73,7 @@
<color name="phone_orange_text">#EA580C</color>
<color name="phone_tag_orange_bg">#FFEDD5</color> <!-- 状态标签-橙底(待处理态) -->
<color name="phone_tag_orange_text">#EA580C</color>
<color name="phone_danger_bg">#FEE2E2</color> <!-- 危险操作按钮-浅红底ULD管理批量删除 -->
<color name="phone_danger_text">#DC2626</color>
</resources>

View File

@@ -48,6 +48,13 @@ class GjViewModel : BaseViewModel() {
Constant.AuthName.GjcIntExpOutHandover,
ARouterConstants.ACTIVITY_URL_INT_EXP_OUT_HANDOVER
),
// ULD管理属综合管理业务Pad 端在「综合管理」菜单组),手机端首页暂无综合 Tab挂在国际 Tab 下
ActionBean(
"ULD管理",
com.lukouguoji.module_base.R.mipmap.cargo, // 图标复用 Pad 端同款(在 module_base直接引用
Constant.AuthName.ComprehensiveUld, // 权限串与 Pad 端菜单一致
ARouterConstants.ACTIVITY_URL_ULD_LIST
),
).filter { SharedPreferenceUtil.getString(Constant.Share.authList).contains(it.key) }
fun onItemClick(position: Int) {