From 5a019a55c4bfdbbbd043a776441efe569d819c19 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Wed, 29 Jul 2026 16:30:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90ULD=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E9=A1=B5=E9=9D=A25.5=E5=AF=B8=E6=89=8B=E6=9C=BA=E7=AB=AF?= =?UTF-8?q?=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 手机版列表(三色状态标签卡片 + 筛选弹层 + 浮动新增 + 全选/批量删除)、 一套 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 --- .claude/skills/phone-adapt/SKILL.md | 8 +- .../skills/phone-adapt/references/api-doc.md | 5 + .../phone-adapt/references/components.md | 12 + .../phone-adapt/references/verification.md | 15 +- CHANGELOG.md | 14 + CLAUDE.md | 10 + app/src/debug/AndroidManifest.xml | 12 + .../page/uld/edit/UldEditActivity.kt | 28 ++ .../page/uld/edit/UldEditViewModel.kt | 47 ++- .../page/uld/list/UldListActivity.kt | 64 ++++ .../page/uld/list/UldListViewHolder.kt | 26 +- .../page/uld/list/UldListViewModel.kt | 82 +++- .../res/layout-sw600dp/activity_uld_edit.xml | 171 +++++++++ .../res/layout-sw600dp/activity_uld_list.xml | 122 ++++++ .../main/res/layout-sw600dp/item_uld_list.xml | 254 +++++++++++++ app/src/main/res/layout/activity_uld_edit.xml | 300 ++++++++++----- app/src/main/res/layout/activity_uld_list.xml | 229 +++++++----- app/src/main/res/layout/item_uld_list.xml | 350 ++++++------------ documents/后端接口对接问题清单.xlsx | Bin 12337 -> 14095 bytes .../lukouguoji/module_base/bean/ULDBean.kt | 31 ++ .../module_base/router/ARouterConstants.kt | 2 + .../ui/weight/phone/PhoneBottomBar.kt | 23 ++ .../ui/weight/phone/PhoneFormRow.kt | 232 ++++++++++++ .../ui/weight/phone/PhoneFormRowType.kt | 18 + .../ui/weight/phone/PhoneWidgetKtx.kt | 55 +++ .../main/res/drawable/bg_phone_btn_danger.xml | 16 + .../src/main/res/drawable/bg_phone_fab.xml | 14 + .../res/drawable/bg_phone_tag_red_light.xml | 7 + .../src/main/res/drawable/ic_phone_edit.xml | 11 + .../src/main/res/drawable/ic_phone_trash.xml | 11 + .../main/res/layout/layout_phone_form_row.xml | 92 +++++ module_base/src/main/res/values/colors.xml | 2 + .../sixin/module_p/ui/enter/gj/GjViewModel.kt | 7 + 33 files changed, 1848 insertions(+), 422 deletions(-) create mode 100644 app/src/main/res/layout-sw600dp/activity_uld_edit.xml create mode 100644 app/src/main/res/layout-sw600dp/activity_uld_list.xml create mode 100644 app/src/main/res/layout-sw600dp/item_uld_list.xml create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFormRow.kt create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFormRowType.kt create mode 100644 module_base/src/main/res/drawable/bg_phone_btn_danger.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_fab.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_tag_red_light.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_edit.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_trash.xml create mode 100644 module_base/src/main/res/layout/layout_phone_form_row.xml diff --git a/.claude/skills/phone-adapt/SKILL.md b/.claude/skills/phone-adapt/SKILL.md index 4924e42..8a6fe6a 100644 --- a/.claude/skills/phone-adapt/SKILL.md +++ b/.claude/skills/phone-adapt/SKILL.md @@ -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`—— diff --git a/.claude/skills/phone-adapt/references/api-doc.md b/.claude/skills/phone-adapt/references/api-doc.md index 6368bc0..b7358d6 100644 --- a/.claude/skills/phone-adapt/references/api-doc.md +++ b/.claude/skills/phone-adapt/references/api-doc.md @@ -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 快得多) diff --git a/.claude/skills/phone-adapt/references/components.md b/.claude/skills/phone-adapt/references/components.md index e3a26a0..5d9bc39 100644 --- a/.claude/skills/phone-adapt/references/components.md +++ b/.claude/skills/phone-adapt/references/components.md @@ -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")` 传。 diff --git a/.claude/skills/phone-adapt/references/verification.md b/.claude/skills/phone-adapt/references/verification.md index 4bd91bf..811b0fa 100644 --- a/.claude/skills/phone-adapt/references/verification.md +++ b/.claude/skills/phone-adapt/references/verification.md @@ -46,8 +46,19 @@ adb -s install -r -d app/build/outputs/apk/debug/app-debug.apk adb -s 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 登录后 国际业务只有「板箱过磅」「进港理货」,没有「出库交接」)。这时走下面的直启。 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1370eca..d23c007 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 返回同一批数据)。 diff --git a/CLAUDE.md b/CLAUDE.md index 29d5377..fa2bfc2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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) = - 「国际出港移库」`IntExpMoveActivity` + 「运单详情」`IntExpMoveDetailActivity`(框架参考页) - 「国际出港出库交接」`IntExpOutHandoverActivity` + 「板箱详情」`IntExpOutHandoverDetailActivity` (公共组件首个完整落地页,双端实机验证通过) + - 「ULD管理」`UldListActivity` + `UldEditActivity`(app 模块首个适配页;一套编辑布局覆盖 + 新增/修改/详情三态;批量删除为前端循环调用单条接口;状态三态/来源等 5 项后端缺口见问题清单 #7~#11) - ⏳ **待办**: - `PhoneSearchBar` 接入 AutoQuery 联想(`AutoQueryManager` 目前只对接了 Pad 系组件) - 出库交接 Tab 角标恒 0:`IntExpOutHandover/pageQueryTotal` 出参恒 0(后端缺陷,问题清单 #6), diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml index f0988cb..0ecb42d 100644 --- a/app/src/debug/AndroidManifest.xml +++ b/app/src/debug/AndroidManifest.xml @@ -38,5 +38,17 @@ android:exported="true" tools:replace="android:exported" /> + + + + + + diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/uld/edit/UldEditActivity.kt b/app/src/main/java/com/lukouguoji/aerologic/page/uld/edit/UldEditActivity.kt index 9d2559e..b4410e0 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/uld/edit/UldEditActivity.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/uld/edit/UldEditActivity.kt @@ -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() { override fun layoutId() = R.layout.activity_uld_edit @@ -18,6 +26,26 @@ class UldEditActivity : BaseBindingActivity + options.getOrNull(position)?.let { viewModel.onStatusSelected(it.value) } + } + .show() } companion object { diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/uld/edit/UldEditViewModel.kt b/app/src/main/java/com/lukouguoji/aerologic/page/uld/edit/UldEditViewModel.kt index afed20b..5a5ae29 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/uld/edit/UldEditViewModel.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/uld/edit/UldEditViewModel.kt @@ -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>(emptyList()) + // ========== 手机版(5.5 寸手持端)专用 ========== + + /** 来源选项(本地枚举;后端字段暂不支持,需求已登记 documents/后端接口对接问题清单.xlsx) */ + val sourceEditList = MutableLiveData>( + 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() + } } } } diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/uld/list/UldListActivity.kt b/app/src/main/java/com/lukouguoji/aerologic/page/uld/list/UldListActivity.kt index 6bd4c30..5d11654 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/uld/list/UldListActivity.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/uld/list/UldListActivity.kt @@ -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() { override fun layoutId(): Int { @@ -19,9 +34,13 @@ class UldListActivity : BaseBindingActivity(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { + viewModel.onItemCheckChanged() + } } override fun onResume() { @@ -36,6 +60,46 @@ class UldListActivity : BaseBindingActivity(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(ConstantEvent.EVENT_CHECK_CHANGED).tryEmit("check_changed") + binding.executePendingBindings() + } + + binding.executePendingBindings() } } diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/uld/list/UldListViewModel.kt b/app/src/main/java/com/lukouguoji/aerologic/page/uld/list/UldListViewModel.kt index 72f577f..70fce2a 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/uld/list/UldListViewModel.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/uld/list/UldListViewModel.kt @@ -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>( + listOf( + KeyValue("全部", ""), + KeyValue("空运", "空运"), + KeyValue("陆运", "陆运"), + ) + ) + + // ========== 手机版批量选择状态 ========== + val isAllChecked = MutableLiveData(false) + val selectedCount = MutableLiveData("0") + // 状态下拉列表 val statusList = MutableLiveData>( 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() ?: 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() ?: 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 = + pageModel.rv?.commonAdapter()?.items?.filterIsInstance() + ?.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, 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) } diff --git a/app/src/main/res/layout-sw600dp/activity_uld_edit.xml b/app/src/main/res/layout-sw600dp/activity_uld_edit.xml new file mode 100644 index 0000000..4eb9db6 --- /dev/null +++ b/app/src/main/res/layout-sw600dp/activity_uld_edit.xml @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout-sw600dp/activity_uld_list.xml b/app/src/main/res/layout-sw600dp/activity_uld_list.xml new file mode 100644 index 0000000..e06e2c6 --- /dev/null +++ b/app/src/main/res/layout-sw600dp/activity_uld_list.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout-sw600dp/item_uld_list.xml b/app/src/main/res/layout-sw600dp/item_uld_list.xml new file mode 100644 index 0000000..9e7f379 --- /dev/null +++ b/app/src/main/res/layout-sw600dp/item_uld_list.xml @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_uld_edit.xml b/app/src/main/res/layout/activity_uld_edit.xml index 8460770..55f4848 100644 --- a/app/src/main/res/layout/activity_uld_edit.xml +++ b/app/src/main/res/layout/activity_uld_edit.xml @@ -1,167 +1,267 @@ - + + - + + + + + + + + - + + + + + + + + + android:fillViewport="true" + android:overScrollMode="never"> + android:padding="16dp"> + + android:paddingHorizontal="16dp"> - + + + + - + android:text="状态" + android:textColor="@color/phone_text_label" + android:textSize="15sp" /> - + + android:visibility="@{viewModel.pageType == DetailsPageType.Details ? View.VISIBLE : View.GONE}" /> - + + + + android:gravity="end|center_vertical" + android:orientation="horizontal" + android:visibility="@{viewModel.pageType == DetailsPageType.Details ? View.GONE : View.VISIBLE}"> + + + + - - + + + + enable="@{viewModel.pageType != DetailsPageType.Details}" + hint='@{"请选择所属航司"}' + list="@{viewModel.carrierList}" + title='@{"所属航司"}' + type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.SELECT}" + value="@={viewModel.uldBean.carrier}" /> - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.INPUT}" + value="@={viewModel.uldBean.remark}" /> - - + - - - - - - + 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}" /> + diff --git a/app/src/main/res/layout/activity_uld_list.xml b/app/src/main/res/layout/activity_uld_list.xml index be9908d..e55b7ee 100644 --- a/app/src/main/res/layout/activity_uld_list.xml +++ b/app/src/main/res/layout/activity_uld_list.xml @@ -1,118 +1,175 @@ + - + + + + + - - - + android:background="@color/phone_page_bg"> + android:layout_height="match_parent" + android:orientation="vertical"> - - - - - + + + android:background="@color/white" + android:orientation="vertical" + android:paddingHorizontal="16dp" + android:paddingTop="16dp" + android:paddingBottom="12dp"> - - - + - - - - - + + android:layout_height="0dp" + android:layout_weight="1"> - + - + - + + - + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_uld_list.xml b/app/src/main/res/layout/item_uld_list.xml index 9e7f379..9db6602 100644 --- a/app/src/main/res/layout/item_uld_list.xml +++ b/app/src/main/res/layout/item_uld_list.xml @@ -1,254 +1,148 @@ + + + + + android:layout_marginHorizontal="12dp" + android:layout_marginTop="12dp" + android:background="@drawable/bg_phone_card" + android:orientation="vertical" + android:padding="16dp"> - + + android:layout_height="wrap_content" + android:gravity="center_vertical" + android:orientation="horizontal"> - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + 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" /> - + - + - + + - + + + + + + + + + + + + + + + + + + + diff --git a/documents/后端接口对接问题清单.xlsx b/documents/后端接口对接问题清单.xlsx index 520c677906eb1eaf66f7bd8bac1153d9bb8a0f09..4f79b2c0b2b0a25a53a123ecfc26819886b749a8 100644 GIT binary patch delta 6795 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�SjX*{#Dm{jZ{G`=tjsJ$_<(ZjN&^#VpAXW3bt>Spj7cgxn8!- zrJ}vx@%)1I%)m*WM<g$5Yxd8Jdx{y4EhjMb{JkYe zbxAj4!scaNS)TzS?6FN^N??Yp(X3OO&z^PisF4^s;?vB*GZT$Ylq7SPUsgGI2n-ST zSZU{qYP<05-GzB$lX(;`4OnNif6-Heeu-wS<-EB~m@eG)#~az0T5MramVjcM9ZQ+)^*oIec_g~B{qKvS6X=uDC<>uC6hacm*$NFj9Jav*4=e!KX$JsReK ztd35%AwSiVL+;jXt?Dw~CL@qJMFlv-|FNvZPDIxa&XA2%KdO`_=6NfMn_*ha54dm z3|@KGXOqR^lEx0w@2FrY?vP(ab;1gPVs;OPZ6n`wGOHsNtTn(0xmba`4)fW%v`?o4vrQeB0>AqZY@|*g<+ArAvu?TaIgbX^nfU3J+cgMu4y^aQm2mV9KH$>q03oCRW5RpNm7^RfZ^sBLEofE*I^G06~T+H zpBIU_%J#U<-hZS*({J{)jzs_+LUVYjM2GZLh71ijEIYqGZ4;``DJl*prg-f3HQAJ9 zx~5l&W>s~^f52zDFCV?sJW9b~nToPX+}OO2!`z>FnY0um{q4RRlg#4|g$lIIH$nlD z-Lre^?TQZ2;NyqneURDS$Gxyty41oKAn)YqqdCnfz&PGeXrA8@fg>4;d(5H$c=bHI zn!w~MCT=`sLznjVg#JNU>Bylf)w}M(W2Z_ z2<`lwhE4RiDf?beW??3qwA+$C+<%{v zeHur6l1~+Wif5ej)T#%NxzzU*q}8#<(WYELVy7`U5-8{g%z!O)?+T4AG){?_^torv zzLGN@vFOTa%@9i$H7C=gZNfc?Oa4g5#p@1dtHZHjl(TOIp>>Xq5rl_!@8vj&(s^29 zsFQh_tv9x0T7tT4{d|6JOsn{M8B|0z)-HW;E6ZR9BAW zuYURk+VyhadsfgP1@RB?gw~)})`+)k#%fM* zmm2&q7|g9h%EnS?Su^qdZsH`Dq%{e90BL9kwZ&zy7(_;D#dbJLqqRZxPK4!rR{RfB)4VuA4Ohb%X5kVvrJ!{-A4UV7L% zdkPEP?0TAb`1Az-waws)60G>!eDIeN_iplo|DvV`aFhh!{hOZgm7gbh@c;n(zhp@F W--dtBw|Lb8@D&N}TjZdd=>Gt`V1&;A diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/ULDBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/ULDBean.kt index b690fbe..f197b65 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/ULDBean.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/ULDBean.kt @@ -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" } \ No newline at end of file diff --git a/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt b/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt index ff0003c..700b17f 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt @@ -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" //国际出港 出港运抵 diff --git a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneBottomBar.kt b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneBottomBar.kt index 8d1c88c..8ffef3e 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneBottomBar.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneBottomBar.kt @@ -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 diff --git a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFormRow.kt b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFormRow.kt new file mode 100644 index 0000000..c3bd10d --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFormRow.kt @@ -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 + * + * ``` + */ +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 = 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) { + dispatchFreezeSelfOnly(container) + } + + override fun dispatchRestoreInstanceState(container: SparseArray) { + dispatchThawSelfOnly(container) + } +} diff --git a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFormRowType.kt b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFormRowType.kt new file mode 100644 index 0000000..37900e3 --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFormRowType.kt @@ -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, +} diff --git a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneWidgetKtx.kt b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneWidgetKtx.kt index 326658b..0134839 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneWidgetKtx.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneWidgetKtx.kt @@ -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?) { + 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 } +} diff --git a/module_base/src/main/res/drawable/bg_phone_btn_danger.xml b/module_base/src/main/res/drawable/bg_phone_btn_danger.xml new file mode 100644 index 0000000..8845bc3 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_btn_danger.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_fab.xml b/module_base/src/main/res/drawable/bg_phone_fab.xml new file mode 100644 index 0000000..4966935 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_fab.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_tag_red_light.xml b/module_base/src/main/res/drawable/bg_phone_tag_red_light.xml new file mode 100644 index 0000000..147e1b6 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_tag_red_light.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_edit.xml b/module_base/src/main/res/drawable/ic_phone_edit.xml new file mode 100644 index 0000000..a275720 --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_edit.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_trash.xml b/module_base/src/main/res/drawable/ic_phone_trash.xml new file mode 100644 index 0000000..8db15c3 --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_trash.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/module_base/src/main/res/layout/layout_phone_form_row.xml b/module_base/src/main/res/layout/layout_phone_form_row.xml new file mode 100644 index 0000000..435b425 --- /dev/null +++ b/module_base/src/main/res/layout/layout_phone_form_row.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_base/src/main/res/values/colors.xml b/module_base/src/main/res/values/colors.xml index d88b3ee..8247886 100644 --- a/module_base/src/main/res/values/colors.xml +++ b/module_base/src/main/res/values/colors.xml @@ -73,5 +73,7 @@ #EA580C #FFEDD5 #EA580C + #FEE2E2 + #DC2626 \ No newline at end of file diff --git a/module_p/src/main/java/com/sixin/module_p/ui/enter/gj/GjViewModel.kt b/module_p/src/main/java/com/sixin/module_p/ui/enter/gj/GjViewModel.kt index 81dcab1..6bcb6af 100644 --- a/module_p/src/main/java/com/sixin/module_p/ui/enter/gj/GjViewModel.kt +++ b/module_p/src/main/java/com/sixin/module_p/ui/enter/gj/GjViewModel.kt @@ -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) {