From 3b732c3aec310ac6dbf9a81c612a897039274f3a Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 31 Jul 2026 20:49:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=87=BA=E6=B8=AF?= =?UTF-8?q?=E4=BB=93=E5=BA=93=E4=B8=8E=E8=BF=9B=E6=B8=AF=E4=BB=93=E5=BA=93?= =?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 出港仓库(07,module_gjc): - IntExpStorageUseActivity 手机布局:搜索行+三格统计(总票数/未清仓/已清仓, clearNormal=0/1 双 pageQueryTotal 仅手机发起)+卡片级四操作按钮(清仓/修改 库位/出库/入库,已清仓置灰),取代平板勾选+底部批量条,复用既有 performXxx 链路 - 详情/运单追踪复用出港查询已适配页(GjcQueryDetailsActivity/LogDetailActivity),零新增页面 - 清仓/入库/修改库位弹框双变体化(手机底部弹层);修改库位手机版增加「原库位」单选; 出库确认 AlertDialog → ConfirmDialogModel(项目强制规范) 进港仓库(08,module_gjj,07 的进港镜像): - IntImpStorageUseActivity 手机布局:搜索框「运单号/航班号」分流(含字母→fno, 抓包证实)+始发站字段/筛选(fdep 入参) - 进港详情 IntImpQueryDetailsActivity + 3 Fragment 首次手机适配(报文区 3 项, 件重区直取 inPc/inWeight,库位卡片优先中文姓名) - 修改库位手机弹层「原库位」只列未出库库位(沿用平板校验) 公共:GjcMaWb 增加 isCleared 计算属性;新增 bg_phone_btn_disabled;手机首页 「国际」Tab 增加出港仓库/进港仓库入口;debug manifest 直启项 验证:双端 Proxyman Map Local mock 口径验证通过(开发机不在内网),平板回归一致, 崩溃 0;后端缺口 5 项登记问题清单 #23~#27(筛选入参缺失/clearNormal 分项统计与 detail 推断字段待内网实测) Co-Authored-By: Claude Fable 5 --- .../skills/phone-adapt/references/api-doc.md | 16 + .../skills/phone-adapt/references/proxyman.md | 4 + CHANGELOG.md | 52 ++ CLAUDE.md | 17 + app/src/debug/AndroidManifest.xml | 18 + documents/后端接口对接问题清单.xlsx | Bin 20336 -> 21738 bytes .../lukouguoji/module_base/bean/GjcMaWb.kt | 7 + .../res/drawable/bg_phone_btn_disabled.xml | 7 + .../gjc/activity/IntExpStorageUseActivity.kt | 71 +- .../gjc/dialog/IntExpInStorageDialogModel.kt | 6 +- .../dialog/IntExpModifyStorageDialogModel.kt | 35 +- .../gjc/dialog/IntExpMoveClearDialogModel.kt | 6 +- .../gjc/holder/IntExpStorageUseViewHolder.kt | 54 +- .../viewModel/IntExpStorageUseViewModel.kt | 107 ++- .../activity_int_exp_storage_use.xml | 253 +++++++ .../dialog_int_exp_in_storage.xml | 87 +++ .../dialog_int_exp_modify_storage.xml | 87 +++ .../dialog_int_exp_move_clear.xml | 86 +++ .../item_int_exp_storage_use.xml | 419 ++++++++++++ .../item_int_exp_storage_use_sub.xml | 0 .../layout/activity_int_exp_storage_use.xml | 496 ++++++++------ .../res/layout/dialog_int_exp_in_storage.xml | 108 ++- .../layout/dialog_int_exp_modify_storage.xml | 118 ++-- .../res/layout/dialog_int_exp_move_clear.xml | 107 ++- .../res/layout/item_int_exp_storage_use.xml | 599 +++++++--------- .../gjj/activity/IntImpStorageUseActivity.kt | 55 +- .../gjj/dialog/IntImpInStorageDialogModel.kt | 5 +- .../dialog/IntImpModifyStorageDialogModel.kt | 35 +- .../gjj/dialog/IntImpMoveClearDialogModel.kt | 5 +- .../gjj/holder/IntImpStorageUseViewHolder.kt | 67 +- .../viewModel/IntImpQueryDetailsViewModel.kt | 33 + .../viewModel/IntImpStorageUseViewModel.kt | 126 +++- .../activity_int_imp_query_details.xml | 124 ++++ .../activity_int_imp_storage_use.xml | 253 +++++++ .../dialog_int_imp_in_storage.xml | 87 +++ .../dialog_int_imp_modify_storage.xml | 87 +++ .../dialog_int_imp_move_clear.xml | 86 +++ .../fragment_int_imp_query_storage.xml | 136 ++++ .../fragment_int_imp_query_warehouse.xml | 146 ++++ .../fragment_int_imp_query_waybill.xml | 336 +++++++++ .../item_int_imp_query_storage.xml | 99 +++ .../item_int_imp_query_warehouse.xml | 109 +++ .../item_int_imp_storage_use.xml | 433 ++++++++++++ .../item_int_imp_storage_use_sub.xml | 0 .../layout/activity_int_imp_query_details.xml | 81 ++- .../layout/activity_int_imp_storage_use.xml | 498 ++++++++------ .../res/layout/dialog_int_imp_in_storage.xml | 108 ++- .../layout/dialog_int_imp_modify_storage.xml | 118 ++-- .../res/layout/dialog_int_imp_move_clear.xml | 107 ++- .../layout/fragment_int_imp_query_storage.xml | 149 +--- .../fragment_int_imp_query_warehouse.xml | 159 +---- .../layout/fragment_int_imp_query_waybill.xml | 546 ++++++++------- .../res/layout/item_int_imp_query_storage.xml | 148 ++-- .../layout/item_int_imp_query_warehouse.xml | 181 ++--- .../res/layout/item_int_imp_storage_use.xml | 639 +++++++----------- .../sixin/module_p/ui/enter/gj/GjViewModel.kt | 12 + .../res/drawable-xxhdpi/gjc_cang_ku_icon.png | Bin 0 -> 32161 bytes 57 files changed, 5473 insertions(+), 2255 deletions(-) create mode 100644 module_base/src/main/res/drawable/bg_phone_btn_disabled.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/activity_int_exp_storage_use.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_in_storage.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_modify_storage.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_move_clear.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/item_int_exp_storage_use.xml rename module_gjc/src/main/res/{layout => layout-sw600dp}/item_int_exp_storage_use_sub.xml (100%) create mode 100644 module_gjj/src/main/res/layout-sw600dp/activity_int_imp_query_details.xml create mode 100644 module_gjj/src/main/res/layout-sw600dp/activity_int_imp_storage_use.xml create mode 100644 module_gjj/src/main/res/layout-sw600dp/dialog_int_imp_in_storage.xml create mode 100644 module_gjj/src/main/res/layout-sw600dp/dialog_int_imp_modify_storage.xml create mode 100644 module_gjj/src/main/res/layout-sw600dp/dialog_int_imp_move_clear.xml create mode 100644 module_gjj/src/main/res/layout-sw600dp/fragment_int_imp_query_storage.xml create mode 100644 module_gjj/src/main/res/layout-sw600dp/fragment_int_imp_query_warehouse.xml create mode 100644 module_gjj/src/main/res/layout-sw600dp/fragment_int_imp_query_waybill.xml create mode 100644 module_gjj/src/main/res/layout-sw600dp/item_int_imp_query_storage.xml create mode 100644 module_gjj/src/main/res/layout-sw600dp/item_int_imp_query_warehouse.xml create mode 100644 module_gjj/src/main/res/layout-sw600dp/item_int_imp_storage_use.xml rename module_gjj/src/main/res/{layout => layout-sw600dp}/item_int_imp_storage_use_sub.xml (100%) create mode 100644 module_p/src/main/res/drawable-xxhdpi/gjc_cang_ku_icon.png diff --git a/.claude/skills/phone-adapt/references/api-doc.md b/.claude/skills/phone-adapt/references/api-doc.md index 057ce55..62c4e22 100644 --- a/.claude/skills/phone-adapt/references/api-doc.md +++ b/.claude/skills/phone-adapt/references/api-doc.md @@ -85,6 +85,22 @@ curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \ 详情「入库件数/入库重量」= `warehouseList` 各批次 pc/weight 求和(mock 与实测均吻合); 卡片状态推断口径:`fclose` 非空=已离港、否则 `opDate` 非空=已入库; 特码字典沿用 `DictUtils.getSpecialCodeList(flag=1, ieFlag="")`(ieFlag 必须空串) +- `IntExpStorageUse`(出港仓库,2026-07-31 文档核对,内网 A/B 未测——当日开发机不在内网): + `pageQuery`/`pageQueryTotal` 同一套入参 schema:`fdate`/`fno`/`wbNo`/`likeNo`/`spCode`/`dest`/ + `agentCode`/`location`/`clearNormal`/`checkIn`/`reviewStatus`/`dep`/`hno`/`prefix`;设计稿筛选的 + **运单类型/业务类型/品名(中) 均无入参**(`awbType`/`businessType`/`goodsCn`,缺口 #23); + 手机三格统计按 `clearNormal=0/1` 各调一次 `pageQueryTotal` 取 `wbNumber`,该过滤**是否真实生效 + 待内网 A/B**(缺口 #24,参照 isFclose 有定义但被忽略的先例);出参 `clearNormal` 0=未清仓/1=已清仓 + (卡片标签与「清仓」按钮置灰按 ==\"1\" 判定);详情复用 `IntExpSearch/detail`(maWbId Query 参数) +- `IntImpStorage`(进港仓库,2026-07-31 文档核对;**注意前端 Api.kt 路径前缀是 `IntImpStorage` + 不是 `IntImpStorageUse`**,api-doc 按后者搜不到):`pageQuery`/`pageQueryTotal` 同一套入参: + `fdate`/`fno`/`wbNo`/`hno`/`fdep`(始发站)/`location`/`clearNormal`/`fid`;比出港仓库还少 + `agentCode`/`spCode`/`dest`——设计稿筛选的代理/特码/运单类型/业务类型/品名(中) **5 项均无入参** + (缺口 #25);分项统计与 clearNormal 过滤待实测同 #24(记为 #26);详情复用 + `IntImpSearch/detail`(Body 传 `prefix`+`no`,出参 `data.maWb` 无 schema,字段 key 以平板绑定为准: + `awbPc`/`awbWeight`/`cashWeight`/`inPc`/`inWeight`/`lockState`(0/1 需转中文)/`mftStatus` 原始舱单/ + `tallyStatus` 理货报告/`command` 海关放行/`by1` 承运人/`dlvTime` 出库时间;`dep`/`dest1`/`dest`/ + `unNumber`/`opDate` 为按出港推断,待实测 #27) - `IntExpCheckIn`(出港计重,2026-07-29 内网实测):`likeNo` **并非任意模糊**——按 8 位 `no` 匹配(11 位 wbNo 或部分号均 0 条),11 位全号必须走 `wbNo`;`checkIn`/`checkInList` 文档有定义但 `pageQuery`/`pageQueryTotal` **均静默忽略**(缺口 #12,待计重/计重中计数依赖); diff --git a/.claude/skills/phone-adapt/references/proxyman.md b/.claude/skills/phone-adapt/references/proxyman.md index 185056b..d0a2aa4 100644 --- a/.claude/skills/phone-adapt/references/proxyman.md +++ b/.claude/skills/phone-adapt/references/proxyman.md @@ -59,6 +59,10 @@ isFclose 这类「参数是否生效」的 A/B 实验用这条链。给后端提 响应结构照抄真实 flow 的顶层结构(如 pageQuery 是裸 PageInfo:`{total, list, pages, ...}`, 不要包 `{status, data}`)。 +⚠️ 实测坑(2026-07-31 出港仓库):mock `BaseResultBean` 包装的接口(pageQueryTotal/detail 等)时, +**`status` 必须写 `"1"`**——`BaseResultBean.verifySuccess()` 判 `status == "1"`,写 "200" 会被当失败 +静默丢弃(UI 保持默认值,无任何报错,排查靠 flow 已命中但 UI 不变这一矛盾现象)。 + ⚠️ 实测坑:mock 响应到达后 UI 渲染可能滞后(冷启动首帧 Davey 卡顿 2s+), **截图断言前先 `ui_probe texts` 确认数据已上屏**——这次就因截图太早误判过一轮「mock 没生效」, 其实 `get_flow_detail` 里 `matchedTools: ["Map Local"]` 早已证明规则命中,UI 只是还没画完。 diff --git a/CHANGELOG.md b/CHANGELOG.md index bb6c835..a753159 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,42 @@ ## [Unreleased] ### 新增 (Added) +- 「进港仓库」5.5 寸手机端适配(设计稿 08_进港仓库,07 出港仓库的进港镜像 + 进港详情页首次适配): + 列表 `IntImpStorageUseActivity`(module_gjj,首页菜单实际跳转页;旧版 `GjjWareHouseActivity` + 路由已注释弃用)手机布局 = PhoneSearchBar(placeholder「搜索运单号/航班号」,`phoneSearchClick` + 分流:含字母→fno、其余→wbNo,实机抓包证实)+ 三格统计(总票数/未清仓/已清仓,clearNormal=0/1 + 双 total)+ 卡片四操作按钮(清仓/修改库位/出库/入库,已清仓置灰)+ 卡片字段件数/重量/航班号/ + **始发站**(bean.dep,出港为目的站);筛选弹层 8 项(始发站走 fdep 入参;代理/特码/运单类型/ + 业务类型/品名中 5 项为后端未定义入参,预留传参) +- 进港详情页 `IntImpQueryDetailsActivity` + 3 Fragment(运单/仓库/库位信息)首次手机适配: + 移植 06 出港详情手机布局,报文区按设计稿 3 项(原始舱单 mftStatus/理货报告 tallyStatus/ + 海关放行 command),件重区直取 detail 出参 awbPc/awbWeight/cashWeight/inPc/inWeight + (进港自带无需求和),库位卡片优先显示中文姓名(inOpName/outOpName); + ViewModel 增加 str/strOr/dec 取值帮助(与出港同口径) +- 进港版 3 个操作弹框双变体化(清仓/入库/修改库位,手机底部弹层);修改库位手机版增加 + 「原库位」单选且**只列未出库库位**(沿用平板「已出库不允许修改」校验,卡片级操作时全部已出库 + toast 拦截),单库位默认选中 +- 手机首页「国际」Tab 增加「进港仓库」入口(权限 AppGjjWareHouse=Constant.AuthName.GjjWareHouseActivity 对应权限串,图标复用出港仓库同款) +- 后端缺口 3 项登记问题清单 #25~#27(pageQuery 无代理/特码/运单类型/业务类型/品名中 5 项筛选 + 入参;clearNormal 分项统计待实测;detail 出参 dep/dest1/dest/unNumber/opDate 字段待实测确认) +- 「出港仓库」5.5 寸手机端适配(设计稿 07_出港仓库,详情/运单追踪复用已适配页零新增): + 列表 `IntExpStorageUseActivity` 手机布局 = PhoneSearchBar(运单号 + 扫码 + 筛选)+ 三格统计 + (总票数/未清仓/已清仓,彩色左边条卡片;分项计数按同条件 + `clearNormal=0/1` 各调一次 + `pageQueryTotal`,仅手机形态发起)+ 状态标签卡片(已清仓绿/未清仓橙,`clearNormal=="1"` 判定); + **卡片级四操作按钮**(清仓/修改库位/出库/入库,已清仓时清仓置灰拦截)取代平板的勾选+底部批量条, + 语义等价于「勾选该主单+全部库位」复用既有 `performClear/performModifyStorage/performOutStorage/ + performInStorage` 请求链路;卡片点击进详情(复用出港查询详情 `GjcQueryDetailsActivity` 3 Tab + 运单/仓库/库位信息,运单追踪同样复用 `LogDetailActivity`);筛选弹层 8 项按设计稿完整实现 + (航班日期/航班号/代理/特码/目的站/运单类型/业务类型/品名中,后三项为后端未定义入参,预留传参) +- 清仓/入库/修改库位三个操作弹框(`IntExpMoveClearDialogModel`/`IntExpInStorageDialogModel`/ + `IntExpModifyStorageDialogModel`)双变体化:手机底部弹层(PhoneDataLayout)+ 平板居中弹框不变, + 弹出位置按 `DeviceUtil.isPhone()` 切换;修改库位弹框手机版新增「原库位」单选 + (卡片级操作时运单可能有多个库位,构造参数 `sourceStorageList` 传入,单库位默认选中,平板路径不受影响) +- 出库二次确认由系统 `AlertDialog` 改为项目规范的 `ConfirmDialogModel`(平板批量出库与手机卡片出库共用) +- 手机首页「国际」Tab 增加「出港仓库」入口(权限 AppIntExpStorageUse,图标复用 Pad 端 gjc_cang_ku_icon) +- `GjcMaWb` 新增 `isCleared` 手机版计算属性;新增手机版资源 `bg_phone_btn_disabled`(灰底禁用按钮) +- 后端缺口 2 项登记问题清单 #23~#24(pageQuery/pageQueryTotal 无 awbType/businessType/goodsCn + 筛选入参;pageQueryTotal 的 clearNormal 分项统计过滤待内网 A/B 实测确认) - 「出港查询」5.5 寸手机端适配(设计稿 06_出港查询,含列表/详情/运单追踪三页): 列表 `GjcQueryActivity` 手机布局 = PhoneSearchBar(运单号 + 扫码 + 筛选)+ 三格统计 (总票数/已入库/已离港,彩色左边条卡片)+ 状态标签卡片(已离港绿/已入库橙/未入库灰, @@ -34,6 +70,22 @@ (已回归出港计重 4 项弹层,行为不变) ### 验证 (Verified) +- 进港仓库双端验证通过(2026-07-31,同出港仓库为 Proxyman Map Local mock 口径): + 手机端登录→国际 Tab→进港仓库菜单入口、三格统计、三种卡片形态(含空值 "--" 兜底)、 + 详情 3 Tab 全字段(锁定状态转中文、库位中文姓名、时间截断、空值兜底)、四操作弹框、 + 已出库库位过滤(双库位卡片原库位仅列未出库项并默认选中)、无库位/已清仓拦截、 + 筛选弹层 8 项、搜索分流实机抓包证实(输入 MU1111 → 请求体 fno="MU1111"、wbNo=null)、 + 冷启动方向恒竖屏、崩溃 0;平板端回归:5 搜索条/全选/底部统计/4 批量按钮与改造前一致,崩溃 0。 + **待内网补测**:clearNormal 分项统计 A/B、detail 推断字段(dep/dest1/dest/unNumber/opDate)、 + 四操作真实提交链路 +- 出港仓库双端验证通过(2026-07-31,开发机不在内网 → 全程 Proxyman Map Local mock 口径): + 手机端登录→国际 Tab→出港仓库菜单入口、三格统计渲染、三种卡片形态(已清仓置灰清仓/未清仓/ + 全空字段 "--" 兜底)、四操作按钮(清仓/入库底部弹层、修改库位弹层含原库位默认选中、 + 出库 ConfirmDialogModel 文案带运单号与库位数、无库位卡片 toast 拦截、已清仓清仓点击拦截)、 + 筛选弹层 8 项滚动 + 底部按钮可见、卡片点击进详情(Proxyman flow 证实 maWbId 正确传参且 + detail mock 命中)、详情右上运单追踪跳转、冷启动方向恒竖屏(ROTATION_0×3 采样)、崩溃 0; + 平板端同页面回归:5 搜索条/全选/底部统计/4 批量按钮与改造前一致,崩溃 0。 + **待内网补测**:clearNormal 分项统计 A/B、agentCode/spCode/dest 筛选实测、四操作真实提交链路 - 出港查询双端实机验证通过(2026-07-31,内网真实数据 2026-06-09 共 14 票): 手机端登录→国际 Tab→出港查询菜单入口、列表加载/状态标签/三格统计(10+4=14 与卡片一致)、 筛选弹层(日期滚轮、特码/代理下拉真实取数、重置、确认后重新查询)、运单号搜索、扫码拉起、 diff --git a/CLAUDE.md b/CLAUDE.md index e7ae668..0481338 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1064,6 +1064,8 @@ DataBinding 适配器统一放在 `PhoneWidgetKtx.kt`(同名属性按控件类 出港查询追加:`ic_phone_package`(件数)、`ic_phone_tag`(特码)、`bg_phone_dot_blue/gray`(状态圆点); `PhoneFilterPanel` 内容插槽已内置 ScrollView(筛选项超屏时收缩滚动,底部按钮始终可见—— 9 个筛选项曾把「重置/确认」挤出屏幕)。 +出港仓库追加:`bg_phone_btn_disabled`(灰底禁用按钮,与 `bg_phone_btn_weak` 同 10dp 圆角, +卡片操作按钮禁用态配 `phone_tag_gray_text` 文字)。 ⚠️ **弹层与浮动按钮的层级**:`PhoneFilterPanel` 默认无 elevation,页面里有带 elevation 的浮动按钮(FAB)时 会穿透到弹层之上——给弹层实例加 `android:elevation="8dp"`(大于 FAB 的 6dp)。 @@ -1132,6 +1134,21 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = `.checked.set(...)` 会崩溃——接收方 `initOnCreated` 必须对列表 `.map { it.copy() }` 补上。 2026-07-30 review 修正:状态重置弹框改手机底部弹层(弹框双变体首例,见改造步骤第 6 条)、 主列表/回执页补空态、分单浮层补「回执」、分单统计加分母、Tab 角标初始 0 + - 「进港仓库」`IntImpStorageUseActivity`(module_gjj,07 出港仓库的进港镜像;**首页菜单实际跳转页, + 旧版 `GjjWareHouseActivity` 路由已注释弃用**。差异:卡片/筛选用始发站(fdep 入参)替代目的站; + 搜索框「运单号/航班号」分流(含字母→fno、其余→wbNo,抓包证实);筛选 5 项无入参(缺口 #25, + 比出港多 2 项);连带首次适配进港详情 `IntImpQueryDetailsActivity` + 3 Fragment(报文区 3 项: + 原始舱单/理货报告/海关放行,件重区直取 inPc/inWeight 无需求和,detail keys 以平板绑定为准 + + dep/dest1/dest/unNumber/opDate 按出港推断待实测 #27);修改库位手机弹层「原库位」只列未出库 + 库位(沿用平板校验);**前端接口前缀是 `IntImpStorage` 不是 `IntImpStorageUse`**,api-doc 按 + 后者搜不到) + - 「出港仓库」`IntExpStorageUseActivity`(嵌套多选列表页型的首个适配:平板「勾选主/子列表 + + 底部批量操作」在手机上改为**卡片级四按钮**(清仓/修改库位/出库/入库,已清仓置灰),语义等价 + 「勾选该主单+全部库位」直接复用既有 performXxx 链路,ViewHolder 对双侧独有 id 全判空; + 三格统计 总票数/未清仓/已清仓(后两格 = 同条件 + `clearNormal=0/1` 各调一次 pageQueryTotal, + 过滤是否生效待内网 A/B,缺口 #24);筛选弹层 8 项中运单类型/业务类型/品名(中) 为后端未定义 + 入参(缺口 #23,预留传参);三个操作弹框双变体化 + 手机版修改库位弹层加「原库位」单选; + 出库确认 AlertDialog → ConfirmDialogModel;详情与运单追踪完全复用出港查询已适配页,零新增页面) - 「出港查询」`GjcQueryActivity`(列表:三格统计 总票数/已入库/已离港 + 卡片状态标签, 状态为前端推断:`fclose` 非空=已离港/`opDate` 非空=已入库;筛选弹层 9 项,日期起止与代理 从平板搜索行并入,特码改下拉 `getSpecialCodeList(flag=1, ieFlag="")`;分项统计为已加载 diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml index a344348..dcccdf0 100644 --- a/app/src/debug/AndroidManifest.xml +++ b/app/src/debug/AndroidManifest.xml @@ -122,5 +122,23 @@ android:exported="true" tools:replace="android:exported" /> + + + + + + + + + diff --git a/documents/后端接口对接问题清单.xlsx b/documents/后端接口对接问题清单.xlsx index 59eab0a388cca601ea761164e2e749f40b5fc4e5..def4f7d2ecab9a4c8e8dc861403cdfc4d61e0f17 100644 GIT binary patch delta 10566 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 + + + + + diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt index 34d286a..ce52c87 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpStorageUseActivity.kt @@ -3,7 +3,6 @@ package com.lukouguoji.gjc.activity import android.app.Activity import android.content.Intent import android.os.Bundle -import androidx.appcompat.app.AlertDialog import com.alibaba.android.arouter.facade.annotation.Route import com.lukouguoji.gjc.R import com.lukouguoji.gjc.databinding.ActivityIntExpStorageUseBinding @@ -18,7 +17,9 @@ import com.lukouguoji.module_base.impl.FlowBus import com.lukouguoji.module_base.impl.observe import com.lukouguoji.module_base.ktx.commonAdapter import com.lukouguoji.module_base.ktx.showToast +import com.lukouguoji.module_base.model.ConfirmDialogModel import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil /** * 国际出港-仓库 @@ -31,10 +32,13 @@ class IntExpStorageUseActivity : override fun viewModelClass() = IntExpStorageUseViewModel::class.java override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("国际出港仓库") + setBackArrow(if (DeviceUtil.isPhone()) "出港仓库" else "国际出港仓库") binding.viewModel = viewModel binding.activity = this + // 手机形态专属:筛选字典 + 未清仓/已清仓分项统计(平板不调用,行为零变化) + if (DeviceUtil.isPhone()) viewModel.initPhoneExtras() + // 绑定分页 viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this) @@ -139,15 +143,60 @@ class IntExpStorageUseActivity : } // 显示二次确认对话框 - AlertDialog.Builder(this) - .setTitle("出库确认") - .setMessage("确定要将选中的 ${selectedStorageUseList.size} 个库位执行出库操作吗?") - .setPositiveButton("确定") { _, _ -> - // 用户确认后,执行出库操作 - viewModel.performOutStorage(selectedStorageUseList) - } - .setNegativeButton("取消", null) - .show() + ConfirmDialogModel( + message = "确定要将选中的 ${selectedStorageUseList.size} 个库位执行出库操作吗?", + title = "出库确认" + ) { + // 用户确认后,执行出库操作 + viewModel.performOutStorage(selectedStorageUseList) + }.show(this) + } + + // ==================== 5.5寸手机版:卡片级操作 ==================== + // 语义等价于「勾选该主单 + 其全部库位」再执行平板的批量操作,复用 performXxx 请求链路。 + + /** 卡片「清仓」(已清仓的卡片按钮置灰,ViewHolder 已拦截) */ + fun cardClear(bean: com.lukouguoji.module_base.bean.GjcMaWb) { + val maWbListForClear = listOf(bean.copy(storageUseList = bean.storageUseList ?: emptyList())) + IntExpMoveClearDialogModel { dialog -> + viewModel.performClear(dialog.clearNormal.value ?: "", maWbListForClear) + }.show(this) + } + + /** 卡片「修改库位」:弹层内先单选原库位(单库位时默认选中)再选新库位 */ + fun cardModifyStorage(bean: com.lukouguoji.module_base.bean.GjcMaWb) { + val storageList = bean.storageUseList ?: emptyList() + if (storageList.isEmpty()) { + showToast("该运单暂无库位") + return + } + IntExpModifyStorageDialogModel(sourceStorageList = storageList) { dialog -> + val sourceStorage = dialog.selectedSourceStorage ?: return@IntExpModifyStorageDialogModel + viewModel.performModifyStorage(dialog.locationName, dialog.locationId, sourceStorage) + }.show(this) + } + + /** 卡片「出库」:该运单全部库位出库(与平板勾选主单后出库同语义) */ + fun cardOutStorage(bean: com.lukouguoji.module_base.bean.GjcMaWb) { + val storageList = bean.storageUseList ?: emptyList() + if (storageList.isEmpty()) { + showToast("该运单暂无库位") + return + } + ConfirmDialogModel( + message = "确定要将运单 ${bean.wbNo} 的 ${storageList.size} 个库位执行出库操作吗?", + title = "出库确认" + ) { + viewModel.performOutStorage(storageList) + }.show(this) + } + + /** 卡片「入库」:弹层选库位后整票入库 */ + fun cardInStorage(bean: com.lukouguoji.module_base.bean.GjcMaWb) { + val maWbListForInStorage = listOf(bean.copy(storageUseList = bean.storageUseList ?: emptyList())) + IntExpInStorageDialogModel { dialog -> + viewModel.performInStorage(dialog.locationName, dialog.locationId, maWbListForInStorage) + }.show(this) } /** diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpInStorageDialogModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpInStorageDialogModel.kt index bac3a9c..46231ef 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpInStorageDialogModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpInStorageDialogModel.kt @@ -9,14 +9,18 @@ import com.lukouguoji.module_base.http.net.NetApply import com.lukouguoji.module_base.ktx.launchCollect import com.lukouguoji.module_base.ktx.showToast import com.lukouguoji.module_base.ktx.verifyNullOrEmpty +import com.lukouguoji.module_base.util.DeviceUtil import dev.utils.app.info.KeyValue /** * 国际出港仓库 - 入库操作对话框 + * 手机为底部弹层(layout/ 变体),平板为居中弹框(layout-sw600dp/ 变体) */ class IntExpInStorageDialogModel( private val callback: (IntExpInStorageDialogModel) -> Unit -) : BaseDialogModel(DIALOG_TYPE_CENTER) { +) : BaseDialogModel( + if (DeviceUtil.isPhone()) DIALOG_TYPE_BOTTOM else DIALOG_TYPE_CENTER +) { // 库位列表 val locationList = MutableLiveData>() diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpModifyStorageDialogModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpModifyStorageDialogModel.kt index 2f5fca8..ec11e20 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpModifyStorageDialogModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpModifyStorageDialogModel.kt @@ -8,15 +8,24 @@ import com.lukouguoji.module_base.base.BaseDialogModel import com.lukouguoji.module_base.http.net.NetApply import com.lukouguoji.module_base.ktx.launchCollect import com.lukouguoji.module_base.ktx.showToast +import com.lukouguoji.module_base.bean.GjcStorageUse import com.lukouguoji.module_base.ktx.verifyNullOrEmpty +import com.lukouguoji.module_base.util.DeviceUtil import dev.utils.app.info.KeyValue /** * 国际出港 - 修改库位对话框 + * 手机为底部弹层(layout/ 变体),平板为居中弹框(layout-sw600dp/ 变体)。 + * + * 平板:列表勾选唯一库位后打开,弹框内只选新库位(sourceStorageList 传 null,原库位项不存在于平板布局)。 + * 手机:卡片级操作,运单可能有多个库位——传入该运单库位列表,弹层内先单选「原库位」再选新库位。 */ class IntExpModifyStorageDialogModel( + private val sourceStorageList: List? = null, private val callback: (IntExpModifyStorageDialogModel) -> Unit -) : BaseDialogModel(DIALOG_TYPE_CENTER) { +) : BaseDialogModel( + if (DeviceUtil.isPhone()) DIALOG_TYPE_BOTTOM else DIALOG_TYPE_CENTER +) { // 库位列表 val locationList = MutableLiveData>() @@ -30,6 +39,13 @@ class IntExpModifyStorageDialogModel( // 库位名称 (后端需要的name) var locationName: String = "" + // ========== 手机卡片级操作专属:原库位单选 ========== + val sourceList = MutableLiveData>(emptyList()) + val selectedSourceId = MutableLiveData("") + + // 选中的原库位对象(保存后由调用方取用) + var selectedSourceStorage: GjcStorageUse? = null + override fun layoutId(): Int { return R.layout.dialog_int_exp_modify_storage } @@ -44,6 +60,19 @@ class IntExpModifyStorageDialogModel( locationId = selectedItem?.value ?: "" locationName = selectedItem?.key ?: "" } + + // 手机版:初始化原库位列表,单库位时默认选中 + if (sourceStorageList != null) { + sourceList.value = sourceStorageList.map { + KeyValue(it.location ?: "", it.id?.toString() ?: "") + } + selectedSourceId.observeForever { id -> + selectedSourceStorage = sourceStorageList.find { it.id?.toString() == id } + } + if (sourceStorageList.size == 1) { + selectedSourceId.value = sourceStorageList[0].id?.toString() ?: "" + } + } } /** @@ -65,6 +94,10 @@ class IntExpModifyStorageDialogModel( * 保存按钮点击 */ fun onSaveClick() { + if (sourceStorageList != null && selectedSourceStorage == null) { + showToast("请选择原库位") + return + } if (selectedLocationCode.value.verifyNullOrEmpty("请选择库位")) { return } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpMoveClearDialogModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpMoveClearDialogModel.kt index 8af9afa..2a6e29a 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpMoveClearDialogModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpMoveClearDialogModel.kt @@ -6,14 +6,18 @@ import com.lukouguoji.gjc.R import com.lukouguoji.gjc.databinding.DialogIntExpMoveClearBinding import com.lukouguoji.module_base.base.BaseDialogModel import com.lukouguoji.module_base.ktx.verifyNullOrEmpty +import com.lukouguoji.module_base.util.DeviceUtil import dev.utils.app.info.KeyValue /** * 国际出港移库 - 清仓操作对话框 + * 手机为底部弹层(layout/ 变体),平板为居中弹框(layout-sw600dp/ 变体) */ class IntExpMoveClearDialogModel( private val callback: (IntExpMoveClearDialogModel) -> Unit -) : BaseDialogModel(DIALOG_TYPE_CENTER) { +) : BaseDialogModel( + if (DeviceUtil.isPhone()) DIALOG_TYPE_BOTTOM else DIALOG_TYPE_CENTER +) { // 清仓正常(存储的是 code:"0" 或 "1") val clearNormal = MutableLiveData("") diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseViewHolder.kt index 7013a5a..8109f37 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpStorageUseViewHolder.kt @@ -2,6 +2,8 @@ package com.lukouguoji.gjc.holder import android.view.View import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.activity.GjcQueryDetailsActivity +import com.lukouguoji.gjc.activity.IntExpStorageUseActivity import com.lukouguoji.gjc.databinding.ItemIntExpStorageUseBinding import com.lukouguoji.module_base.adapter.setCommonAdapter import com.lukouguoji.module_base.base.BaseViewHolder @@ -12,6 +14,10 @@ import com.lukouguoji.module_base.ktx.refresh /** * 国际出港-仓库 ViewHolder + * + * 双形态布局:平板变体含 iv_icon/iv_show/rv_sub(多选 + 库位子列表),手机变体含 + * ll/btn_clear/btn_modify/btn_out/btn_in(整卡进详情 + 卡片级四操作按钮)。 + * 单侧独有的 id 在 Binding 基类中为 @Nullable,必须判空访问。 */ class IntExpStorageUseViewHolder(view: View) : BaseViewHolder(view) { @@ -22,8 +28,10 @@ class IntExpStorageUseViewHolder(view: View) : binding.position = position binding.executePendingBindings() + // ==================== 平板:多选 + 子列表 ==================== + // 图标点击切换选择状态(联动子列表) - binding.ivIcon.setOnClickListener { + binding.ivIcon?.setOnClickListener { // 切换主列表项的选择状态 val newCheckedState = !bean.checked.get() bean.checked.set(newCheckedState) @@ -37,25 +45,45 @@ class IntExpStorageUseViewHolder(view: View) : // 刷新UI binding.executePendingBindings() - binding.rvSub.adapter?.notifyDataSetChanged() + binding.rvSub?.adapter?.notifyDataSetChanged() } // 展开按钮点击事件 - binding.ivShow.setOnClickListener { + binding.ivShow?.setOnClickListener { bean.showMore.set(!bean.showMore.get()) } // 初始化库位明细子列表 RecyclerView - setCommonAdapter( - binding.rvSub, - IntExpStorageUseSubViewHolder::class.java, - R.layout.item_int_exp_storage_use_sub - ) + binding.rvSub?.let { rvSub -> + setCommonAdapter( + rvSub, + IntExpStorageUseSubViewHolder::class.java, + R.layout.item_int_exp_storage_use_sub + ) - // 刷新库位明细数据(传递父Bean引用) - val storageUseList = bean.storageUseList ?: emptyList() - // 为每个子列表项设置父Bean引用(通过tag传递) - binding.rvSub.tag = bean - binding.rvSub.refresh(storageUseList) + // 刷新库位明细数据(传递父Bean引用) + val storageUseList = bean.storageUseList ?: emptyList() + // 为每个子列表项设置父Bean引用(通过tag传递) + rvSub.tag = bean + rvSub.refresh(storageUseList) + } + + // ==================== 手机:整卡进详情 + 卡片级操作 ==================== + + val activity = itemView.context as? IntExpStorageUseActivity + + // 整卡点击进详情(复用出港查询详情页,3 Tab 运单/仓库/库位信息) + binding.ll?.setOnClickListener { + GjcQueryDetailsActivity.start(itemView.context, bean.maWbId) + } + + // 清仓(已清仓时置灰不可点,样式由 XML 按 bean.isCleared 切换) + binding.btnClear?.setOnClickListener { + if (!bean.isCleared) activity?.cardClear(bean) + } + + binding.btnModify?.setOnClickListener { activity?.cardModifyStorage(bean) } + binding.btnOut?.setOnClickListener { activity?.cardOutStorage(bean) } + binding.btnIn?.setOnClickListener { activity?.cardInStorage(bean) } } } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt index 4af85b6..152dc19 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpStorageUseViewModel.kt @@ -17,6 +17,7 @@ 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.model.ScanModel +import com.lukouguoji.module_base.util.DictUtils import dev.utils.app.info.KeyValue import kotlinx.coroutines.launch @@ -38,6 +39,89 @@ class IntExpStorageUseViewModel : BasePageViewModel() { val totalPc = MutableLiveData("0") // 总件数 val totalWeight = MutableLiveData("0") // 总重量 + // ========== 5.5寸手机版专属 ========== + // 筛选弹层显隐 + val filterVisible = MutableLiveData(false) + + // 筛选条件(设计稿弹层 8 项中平板没有的 6 项;平板布局无对应控件 → 恒为空 → 不进请求) + val agentId = MutableLiveData("") // 代理(agentCode) + val spCode = MutableLiveData("") // 特码 + val dest = MutableLiveData("") // 目的站 + val awbType = MutableLiveData("") // 运单类型(pageQuery 无此入参,预留,见接口问题清单) + val businessType = MutableLiveData("") // 业务类型(同上预留) + val goodsCn = MutableLiveData("") // 品名(中)(同上预留) + + // 筛选下拉字典(initPhoneExtras 加载,平板不请求) + val agentList = MutableLiveData(listOf(KeyValue("全部", ""))) + val specialCodeList = MutableLiveData>(emptyList()) + val awbTypeList = MutableLiveData>(emptyList()) + val businessTypeList = MutableLiveData( + listOf( + KeyValue("全部", ""), + KeyValue("普货", "1"), + KeyValue("特货", "2") + ) + ) + + // 三格统计:未清仓 / 已清仓(总票数复用 totalWbNumber,服务端全量口径)。 + // 复用 pageQueryTotal 按 clearNormal=0/1 各查一次(入参 schema 含 clearNormal)。 + val unclearedCount = MutableLiveData("0") + val clearedCount = MutableLiveData("0") + + private var phoneExtrasEnabled = false + + /** + * 手机形态专属初始化(Activity 在 DeviceUtil.isPhone() 时调用)。 + * 平板端不调用,请求次数与行为零变化。 + */ + fun initPhoneExtras() { + phoneExtrasEnabled = true + // 代理(与 06 出港查询同源接口) + launchCollect({ NetApply.api.getIntExpAgentList() }) { + onSuccess = { result -> + val list = mutableListOf(KeyValue("全部", "")) + result.data?.forEach { list.add(KeyValue(it.name ?: "", it.code ?: "")) } + agentList.value = list + } + } + // 特码:flag=1 国际;ieFlag 必须留空——传 "E" 后端返回空数组 + DictUtils.getSpecialCodeList(addAll = false, flag = 1, ieFlag = "") { list -> + specialCodeList.postValue(listOf(KeyValue("全部", "")) + list) + } + // 运单类型(type=IO 国际出港) + DictUtils.getWaybillTypeList(type = Constant.businessType.IO, addAll = true) { + awbTypeList.postValue(it) + } + } + + /** 筛选按钮点击 - 打开筛选面板 */ + fun filterClick() { + filterVisible.value = true + } + + /** 关闭筛选面板 */ + fun closeFilter() { + filterVisible.value = false + } + + /** 重置筛选条件 */ + fun resetFilter() { + flightDate.value = "" + flightNo.value = "" + agentId.value = "" + spCode.value = "" + dest.value = "" + awbType.value = "" + businessType.value = "" + goodsCn.value = "" + } + + /** 确认筛选 - 关闭面板并刷新 */ + fun confirmFilter() { + filterVisible.value = false + refresh() + } + // ========== 全选状态 ========== val isAllChecked = MutableLiveData(false) @@ -301,13 +385,20 @@ class IntExpStorageUseViewModel : BasePageViewModel() { * 获取数据 (重写BasePageViewModel) */ override fun getData() { - // 构建搜索条件 + // 构建搜索条件(手机专属 6 项平板恒为空,不进请求;awbType/businessType/goodsCn + // 为 pageQuery 未定义入参,后端静默忽略,补齐后自动生效,见接口问题清单) val filterParams = mapOf( "fdate" to flightDate.value?.ifEmpty { null }, "fno" to flightNo.value?.ifEmpty { null }, "wbNo" to wbNo.value?.ifEmpty { null }, "location" to location.value?.ifEmpty { null }, - "clearNormal" to clearResult.value?.ifEmpty { null } + "clearNormal" to clearResult.value?.ifEmpty { null }, + "agentCode" to agentId.value?.ifEmpty { null }, + "spCode" to spCode.value?.ifEmpty { null }, + "dest" to dest.value?.ifEmpty { null }, + "awbType" to awbType.value?.ifEmpty { null }, + "businessType" to businessType.value?.ifEmpty { null }, + "goodsCn" to goodsCn.value?.ifEmpty { null } ) // 列表参数 (含分页) @@ -339,5 +430,17 @@ class IntExpStorageUseViewModel : BasePageViewModel() { totalWeight.value = (data?.totalWeight ?: 0.0).toString() } } + + // 手机专属:未清仓/已清仓分项统计(同条件 + clearNormal=0/1 各查一次,平板不发) + if (phoneExtrasEnabled) { + val unclearedParams = (filterParams + mapOf("clearNormal" to "0")).toRequestBody() + launchCollect({ NetApply.api.getIntExpStorageUseTotal(unclearedParams) }) { + onSuccess = { unclearedCount.value = (it.data?.wbNumber ?: 0).toString() } + } + val clearedParams = (filterParams + mapOf("clearNormal" to "1")).toRequestBody() + launchCollect({ NetApply.api.getIntExpStorageUseTotal(clearedParams) }) { + onSuccess = { clearedCount.value = (it.data?.wbNumber ?: 0).toString() } + } + } } } diff --git a/module_gjc/src/main/res/layout-sw600dp/activity_int_exp_storage_use.xml b/module_gjc/src/main/res/layout-sw600dp/activity_int_exp_storage_use.xml new file mode 100644 index 0000000..7719350 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/activity_int_exp_storage_use.xml @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_in_storage.xml b/module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_in_storage.xml new file mode 100644 index 0000000..0d6fee6 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_in_storage.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_modify_storage.xml b/module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_modify_storage.xml new file mode 100644 index 0000000..31919b7 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_modify_storage.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_move_clear.xml b/module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_move_clear.xml new file mode 100644 index 0000000..88206ec --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_move_clear.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/item_int_exp_storage_use.xml b/module_gjc/src/main/res/layout-sw600dp/item_int_exp_storage_use.xml new file mode 100644 index 0000000..eea3de2 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/item_int_exp_storage_use.xml @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_int_exp_storage_use_sub.xml b/module_gjc/src/main/res/layout-sw600dp/item_int_exp_storage_use_sub.xml similarity index 100% rename from module_gjc/src/main/res/layout/item_int_exp_storage_use_sub.xml rename to module_gjc/src/main/res/layout-sw600dp/item_int_exp_storage_use_sub.xml diff --git a/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml b/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml index 7719350..1dd552d 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_storage_use.xml @@ -1,253 +1,327 @@ + - + - + + - + android:background="@color/phone_page_bg"> - - - + android:layout_height="match_parent" + android:orientation="vertical"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + hint='@{"请选择航班日期"}' + title='@{"航班日期"}' + type="@{PhoneDataLayoutType.DATE}" + value="@={viewModel.flightDate}" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + hint='@{"请输入航班号"}' + title='@{"航班号"}' + type="@{PhoneDataLayoutType.INPUT}" + value="@={viewModel.flightNo}" /> - - - - - - - - + + hint='@{"请选择代理"}' + list="@{viewModel.agentList}" + title='@{"代理"}' + type="@{PhoneDataLayoutType.SPINNER}" + value="@={viewModel.agentId}" /> - - - - - - - - - - + + hint='@{"请选择特码"}' + list="@{viewModel.specialCodeList}" + title='@{"特码"}' + type="@{PhoneDataLayoutType.SPINNER}" + value="@={viewModel.spCode}" /> - - + + - - + + - - + + - - + + - + - - - + diff --git a/module_gjc/src/main/res/layout/dialog_int_exp_in_storage.xml b/module_gjc/src/main/res/layout/dialog_int_exp_in_storage.xml index 0d6fee6..6b48409 100644 --- a/module_gjc/src/main/res/layout/dialog_int_exp_in_storage.xml +++ b/module_gjc/src/main/res/layout/dialog_int_exp_in_storage.xml @@ -1,8 +1,13 @@ + - + + android:background="@drawable/bg_phone_panel_top" + android:orientation="vertical" + android:paddingHorizontal="20dp" + android:paddingTop="24dp" + android:paddingBottom="32dp"> - - - - - + + android:layout_marginBottom="24dp"> - - + android:gravity="center" + android:text="入库操作" + android:textColor="@color/phone_text_strong" + android:textSize="18sp" + android:textStyle="bold" /> - + - + - - - - - - + + hint='@{"请选择库位"}' + list="@{model.locationList}" + title='@{"库位号"}' + type="@{PhoneDataLayoutType.SPINNER}" + value="@={model.selectedLocationCode}" /> - - - - - + + diff --git a/module_gjc/src/main/res/layout/dialog_int_exp_modify_storage.xml b/module_gjc/src/main/res/layout/dialog_int_exp_modify_storage.xml index 31919b7..c8c192b 100644 --- a/module_gjc/src/main/res/layout/dialog_int_exp_modify_storage.xml +++ b/module_gjc/src/main/res/layout/dialog_int_exp_modify_storage.xml @@ -1,8 +1,14 @@ + - + + android:background="@drawable/bg_phone_panel_top" + android:orientation="vertical" + android:paddingHorizontal="20dp" + android:paddingTop="24dp" + android:paddingBottom="32dp"> - - - - - + + android:layout_marginBottom="24dp"> - - + android:gravity="center" + android:text="修改库位" + android:textColor="@color/phone_text_strong" + android:textSize="18sp" + android:textStyle="bold" /> - + - + - - - - - - + + hint='@{"请选择原库位"}' + list="@{model.sourceList}" + title='@{"原库位"}' + type="@{PhoneDataLayoutType.SPINNER}" + value="@={model.selectedSourceId}" /> - + + - - - + + diff --git a/module_gjc/src/main/res/layout/dialog_int_exp_move_clear.xml b/module_gjc/src/main/res/layout/dialog_int_exp_move_clear.xml index 88206ec..2a301f3 100644 --- a/module_gjc/src/main/res/layout/dialog_int_exp_move_clear.xml +++ b/module_gjc/src/main/res/layout/dialog_int_exp_move_clear.xml @@ -1,8 +1,13 @@ + - + + android:background="@drawable/bg_phone_panel_top" + android:orientation="vertical" + android:paddingHorizontal="20dp" + android:paddingTop="24dp" + android:paddingBottom="32dp"> - - - - - + + android:layout_marginBottom="24dp"> - - + android:gravity="center" + android:text="清仓操作" + android:textColor="@color/phone_text_strong" + android:textSize="18sp" + android:textStyle="bold" /> - + - + - - - - - - + + hint='@{"请选择清仓正常"}' + list="@{model.clearNormalList}" + title='@{"清仓正常"}' + type="@{PhoneDataLayoutType.SPINNER}" + value="@={model.clearNormal}" /> - - - - - + + diff --git a/module_gjc/src/main/res/layout/item_int_exp_storage_use.xml b/module_gjc/src/main/res/layout/item_int_exp_storage_use.xml index eea3de2..ebbef2a 100644 --- a/module_gjc/src/main/res/layout/item_int_exp_storage_use.xml +++ b/module_gjc/src/main/res/layout/item_int_exp_storage_use.xml @@ -1,7 +1,23 @@ + + xmlns:tools="http://schemas.android.com/tools"> @@ -16,404 +32,243 @@ type="Integer" /> - - + android:layout_marginHorizontal="16dp" + android:layout_marginTop="12dp" + android:background="@drawable/bg_phone_card" + android:orientation="vertical" + android:padding="14dp"> - + + android:gravity="center_vertical" + android:orientation="horizontal"> - - + + + android:layout_weight="1" + android:text="@{bean.wbNo}" + android:textColor="@color/phone_text_title" + android:textSize="16sp" + android:textStyle="bold" + tools:text="78133363396" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + android:layout_marginStart="8dp" + android:background="@drawable/bg_phone_tag_green" + android:gravity="center" + android:paddingHorizontal="8dp" + android:text="已清仓" + android:textColor="@color/phone_tag_green_text" + android:textSize="11sp" + android:visibility="@{bean.isCleared ? View.VISIBLE : View.GONE}" /> + + + + + - + + android:layout_marginTop="12dp" + android:orientation="horizontal"> - + android:layout_weight="1" + android:gravity="center_vertical" + android:orientation="horizontal"> + + - - - - - - - - - - + android:layout_marginStart="6dp" + android:text='@{"件数:" + (bean.pc != null ? String.valueOf(bean.pc) : "--")}' + android:textColor="@color/phone_text_body" + android:textSize="13sp" + tools:text="件数:111" /> - - - - + android:layout_weight="1" + android:gravity="center_vertical" + android:orientation="horizontal"> + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpStorageUseActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpStorageUseActivity.kt index 43c7c77..2447fd8 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpStorageUseActivity.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpStorageUseActivity.kt @@ -19,6 +19,7 @@ import com.lukouguoji.module_base.impl.observe import com.lukouguoji.module_base.ktx.commonAdapter import com.lukouguoji.module_base.ktx.showToast import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil /** * 国际进港-仓库 @@ -31,10 +32,13 @@ class IntImpStorageUseActivity : override fun viewModelClass() = IntImpStorageUseViewModel::class.java override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("国际进港仓库") + setBackArrow(if (DeviceUtil.isPhone()) "进港仓库" else "国际进港仓库") binding.viewModel = viewModel binding.activity = this + // 手机形态专属:筛选字典 + 未清仓/已清仓分项统计(平板不调用,行为零变化) + if (DeviceUtil.isPhone()) viewModel.initPhoneExtras() + // 绑定分页 viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this) @@ -182,6 +186,55 @@ class IntImpStorageUseActivity : }.show(this) } + // ==================== 5.5寸手机版:卡片级操作 ==================== + // 语义等价于「勾选该主单 + 其全部库位」再执行平板的批量操作,复用 performXxx 请求链路。 + + /** 卡片「清仓」(已清仓的卡片按钮置灰,ViewHolder 已拦截) */ + fun cardClear(bean: com.lukouguoji.module_base.bean.GjcMaWb) { + val maWbListForClear = listOf(bean.copy(storageUseList = bean.storageUseList ?: emptyList())) + IntImpMoveClearDialogModel { dialog -> + viewModel.performClear(dialog.clearNormal.value ?: "", maWbListForClear) + }.show(this) + } + + /** 卡片「修改库位」:弹层内先单选原库位(未出库的才可选,单库位时默认选中)再选新库位 */ + fun cardModifyStorage(bean: com.lukouguoji.module_base.bean.GjcMaWb) { + // 已出库的分单不允许修改库位(与平板校验同口径) + val modifiableList = (bean.storageUseList ?: emptyList()) + .filter { it.outOpId.isNullOrEmpty() && it.outDate.isNullOrEmpty() } + if (modifiableList.isEmpty()) { + showToast(if (bean.storageUseList.isNullOrEmpty()) "该运单暂无库位" else "该运单库位均已出库,不允许修改库位") + return + } + IntImpModifyStorageDialogModel(sourceStorageList = modifiableList) { dialog -> + val sourceStorage = dialog.selectedSourceStorage ?: return@IntImpModifyStorageDialogModel + viewModel.performModifyStorage(dialog.locationName, dialog.locationId, sourceStorage) + }.show(this) + } + + /** 卡片「出库」:该运单全部库位出库(与平板勾选主单后出库同语义) */ + fun cardOutStorage(bean: com.lukouguoji.module_base.bean.GjcMaWb) { + val storageList = bean.storageUseList ?: emptyList() + if (storageList.isEmpty()) { + showToast("该运单暂无库位") + return + } + ConfirmDialogModel( + message = "确定要将运单 ${bean.wbNo} 的 ${storageList.size} 个库位执行出库操作吗?", + title = "出库确认" + ) { + viewModel.performOutStorage(storageList) + }.show(this) + } + + /** 卡片「入库」:弹层选库位后整票入库 */ + fun cardInStorage(bean: com.lukouguoji.module_base.bean.GjcMaWb) { + val maWbListForInStorage = listOf(bean.copy(storageUseList = bean.storageUseList ?: emptyList())) + IntImpInStorageDialogModel { dialog -> + viewModel.performInStorage(dialog.locationName, dialog.locationId, maWbListForInStorage) + }.show(this) + } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == Constant.RequestCode.WAYBILL && resultCode == Activity.RESULT_OK) { diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpInStorageDialogModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpInStorageDialogModel.kt index 83de66b..cb6e6fa 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpInStorageDialogModel.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpInStorageDialogModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData import com.lukouguoji.gjj.R import com.lukouguoji.gjj.databinding.DialogIntImpInStorageBinding import com.lukouguoji.module_base.base.BaseDialogModel +import com.lukouguoji.module_base.util.DeviceUtil import com.lukouguoji.module_base.http.net.NetApply import com.lukouguoji.module_base.ktx.launchCollect import com.lukouguoji.module_base.ktx.showToast @@ -16,7 +17,9 @@ import dev.utils.app.info.KeyValue */ class IntImpInStorageDialogModel( private val callback: (IntImpInStorageDialogModel) -> Unit -) : BaseDialogModel(DIALOG_TYPE_CENTER) { +) : BaseDialogModel( + if (DeviceUtil.isPhone()) DIALOG_TYPE_BOTTOM else DIALOG_TYPE_CENTER +) { // 库位列表 val locationList = MutableLiveData>() diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpModifyStorageDialogModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpModifyStorageDialogModel.kt index a3abae6..ba2905c 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpModifyStorageDialogModel.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpModifyStorageDialogModel.kt @@ -8,17 +8,26 @@ import com.lukouguoji.module_base.base.BaseDialogModel import com.lukouguoji.module_base.http.net.NetApply import com.lukouguoji.module_base.ktx.launchCollect import com.lukouguoji.module_base.ktx.showToast +import com.lukouguoji.module_base.bean.GjcStorageUse import com.lukouguoji.module_base.ktx.verifyNullOrEmpty +import com.lukouguoji.module_base.util.DeviceUtil import dev.utils.app.info.KeyValue /** * 国际进港 - 修改库位对话框 + * 手机为底部弹层(layout/ 变体),平板为居中弹框(layout-sw600dp/ 变体)。 + * + * 平板:列表勾选唯一库位后打开,弹框内只选新库位(sourceStorageList 传 null,原库位项不存在于平板布局)。 + * 手机:卡片级操作,运单可能有多个库位——传入该运单未出库的库位列表,弹层内先单选「原库位」再选新库位。 */ class IntImpModifyStorageDialogModel( private val currentLocationId: String = "", private val currentLocationName: String = "", + private val sourceStorageList: List? = null, private val callback: (IntImpModifyStorageDialogModel) -> Unit -) : BaseDialogModel(DIALOG_TYPE_CENTER) { +) : BaseDialogModel( + if (DeviceUtil.isPhone()) DIALOG_TYPE_BOTTOM else DIALOG_TYPE_CENTER +) { // 库位列表 val locationList = MutableLiveData>() @@ -32,6 +41,13 @@ class IntImpModifyStorageDialogModel( // 库位名称 (后端需要的name) var locationName: String = "" + // ========== 手机卡片级操作专属:原库位单选 ========== + val sourceList = MutableLiveData>(emptyList()) + val selectedSourceId = MutableLiveData("") + + // 选中的原库位对象(保存后由调用方取用) + var selectedSourceStorage: GjcStorageUse? = null + override fun layoutId(): Int { return R.layout.dialog_int_imp_modify_storage } @@ -46,6 +62,19 @@ class IntImpModifyStorageDialogModel( locationId = selectedItem?.value ?: "" locationName = selectedItem?.key ?: "" } + + // 手机版:初始化原库位列表,单库位时默认选中 + if (sourceStorageList != null) { + sourceList.value = sourceStorageList.map { + KeyValue(it.location ?: "", it.id?.toString() ?: "") + } + selectedSourceId.observeForever { id -> + selectedSourceStorage = sourceStorageList.find { it.id?.toString() == id } + } + if (sourceStorageList.size == 1) { + selectedSourceId.value = sourceStorageList[0].id?.toString() ?: "" + } + } } /** @@ -76,6 +105,10 @@ class IntImpModifyStorageDialogModel( * 保存按钮点击 */ fun onSaveClick() { + if (sourceStorageList != null && selectedSourceStorage == null) { + showToast("请选择原库位") + return + } if (selectedLocationCode.value.verifyNullOrEmpty("请选择库位")) { return } diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpMoveClearDialogModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpMoveClearDialogModel.kt index a5e5528..c1f0f62 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpMoveClearDialogModel.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/dialog/IntImpMoveClearDialogModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData import com.lukouguoji.gjj.R import com.lukouguoji.gjj.databinding.DialogIntImpMoveClearBinding import com.lukouguoji.module_base.base.BaseDialogModel +import com.lukouguoji.module_base.util.DeviceUtil import com.lukouguoji.module_base.ktx.verifyNullOrEmpty import dev.utils.app.info.KeyValue @@ -13,7 +14,9 @@ import dev.utils.app.info.KeyValue */ class IntImpMoveClearDialogModel( private val callback: (IntImpMoveClearDialogModel) -> Unit -) : BaseDialogModel(DIALOG_TYPE_CENTER) { +) : BaseDialogModel( + if (DeviceUtil.isPhone()) DIALOG_TYPE_BOTTOM else DIALOG_TYPE_CENTER +) { // 清仓正常(存储的是 code:"0" 或 "1") val clearNormal = MutableLiveData("") diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpStorageUseViewHolder.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpStorageUseViewHolder.kt index 68c8fb6..d40ee7e 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpStorageUseViewHolder.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpStorageUseViewHolder.kt @@ -2,6 +2,8 @@ package com.lukouguoji.gjj.holder import android.view.View import com.lukouguoji.gjj.R +import com.lukouguoji.gjj.activity.IntImpQueryDetailsActivity +import com.lukouguoji.gjj.activity.IntImpStorageUseActivity import com.lukouguoji.gjj.databinding.ItemIntImpStorageUseBinding import com.lukouguoji.module_base.adapter.setCommonAdapter import com.lukouguoji.module_base.base.BaseViewHolder @@ -12,6 +14,10 @@ import com.lukouguoji.module_base.ktx.refresh /** * 国际进港-仓库 ViewHolder + * + * 双形态布局:平板变体含 iv_icon/iv_show/rv_sub/ll_header/divider_header/tv_empty + * (多选 + 库位子列表),手机变体含 ll/btn_clear/btn_modify/btn_out/btn_in + * (整卡进详情 + 卡片级四操作按钮)。单侧独有的 id 在 Binding 基类中为 @Nullable,必须判空访问。 */ class IntImpStorageUseViewHolder(view: View) : BaseViewHolder(view) { @@ -22,43 +28,58 @@ class IntImpStorageUseViewHolder(view: View) : binding.position = position binding.executePendingBindings() + // ==================== 平板:多选 + 子列表 ==================== + // 图标点击切换选择状态 - binding.ivIcon.setOnClickListener { + binding.ivIcon?.setOnClickListener { bean.checked.set(!bean.checked.get()) FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).tryEmit("check_changed") binding.executePendingBindings() } // 展开按钮点击事件 - binding.ivShow.setOnClickListener { + binding.ivShow?.setOnClickListener { bean.showMore.set(!bean.showMore.get()) } // 初始化库位明细子列表 RecyclerView - setCommonAdapter( - binding.rvSub, - IntImpStorageUseSubViewHolder::class.java, - R.layout.item_int_imp_storage_use_sub - ) + binding.rvSub?.let { rvSub -> + setCommonAdapter( + rvSub, + IntImpStorageUseSubViewHolder::class.java, + R.layout.item_int_imp_storage_use_sub + ) - // 刷新库位明细数据(传递父Bean引用) - val storageUseList = bean.storageUseList ?: emptyList() - binding.rvSub.tag = bean - binding.rvSub.refresh(storageUseList) - updateSubListVisibility(storageUseList.isNotEmpty()) + // 刷新库位明细数据(传递父Bean引用) + val storageUseList = bean.storageUseList ?: emptyList() + rvSub.tag = bean + rvSub.refresh(storageUseList) + updateSubListVisibility(storageUseList.isNotEmpty()) + } + + // ==================== 手机:整卡进详情 + 卡片级操作 ==================== + + val activity = itemView.context as? IntImpStorageUseActivity + + // 整卡点击进详情(复用进港查询详情页,3 Tab 运单/仓库/库位信息) + binding.ll?.setOnClickListener { + IntImpQueryDetailsActivity.start(itemView.context, bean.prefix, bean.no) + } + + // 清仓(已清仓时置灰不可点,样式由 XML 按 bean.isCleared 切换) + binding.btnClear?.setOnClickListener { + if (!bean.isCleared) activity?.cardClear(bean) + } + + binding.btnModify?.setOnClickListener { activity?.cardModifyStorage(bean) } + binding.btnOut?.setOnClickListener { activity?.cardOutStorage(bean) } + binding.btnIn?.setOnClickListener { activity?.cardInStorage(bean) } } private fun updateSubListVisibility(hasData: Boolean) { - if (hasData) { - binding.llHeader.visibility = View.VISIBLE - binding.dividerHeader.visibility = View.VISIBLE - binding.rvSub.visibility = View.VISIBLE - binding.tvEmpty.visibility = View.GONE - } else { - binding.llHeader.visibility = View.GONE - binding.dividerHeader.visibility = View.GONE - binding.rvSub.visibility = View.GONE - binding.tvEmpty.visibility = View.VISIBLE - } + binding.llHeader?.visibility = if (hasData) View.VISIBLE else View.GONE + binding.dividerHeader?.visibility = if (hasData) View.VISIBLE else View.GONE + binding.rvSub?.visibility = if (hasData) View.VISIBLE else View.GONE + binding.tvEmpty?.visibility = if (hasData) View.GONE else View.VISIBLE } } diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpQueryDetailsViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpQueryDetailsViewModel.kt index 05f7480..f0383b9 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpQueryDetailsViewModel.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpQueryDetailsViewModel.kt @@ -61,6 +61,39 @@ class IntImpQueryDetailsViewModel : BaseViewModel() { currentTab.value = index } + // ==================== 5.5寸手机版取值帮助(与出港 GjcQueryDetailsViewModel 同口径) ==================== + + /** + * 从详情 Map 取字符串展示值;数字自动去掉无意义的 .0;空值兜底 "--" + */ + fun str(map: Map?, key: String): String { + val v = map?.get(key) ?: return "--" + val s = when (v) { + is Double -> if (v % 1.0 == 0.0) v.toLong().toString() else v.toString() + else -> v.toString() + } + return s.ifBlank { "--" } + } + + /** + * 依次取第一个非空 key 的展示值(如 by1 优先于 by0) + */ + fun strOr(map: Map?, key: String, fallbackKey: String): String { + val first = str(map, key) + return if (first != "--") first else str(map, fallbackKey) + } + + /** + * 取重量类数值(保留小数形式),空值兜底 "--" + */ + fun dec(map: Map?, key: String): String { + val v = map?.get(key) ?: return "--" + return when (v) { + is Double -> v.toString() + else -> v.toString().ifBlank { "--" } + } + } + /** * 加载详情数据 */ diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpStorageUseViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpStorageUseViewModel.kt index 702680e..5f8e803 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpStorageUseViewModel.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpStorageUseViewModel.kt @@ -18,6 +18,7 @@ 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.model.ScanModel +import com.lukouguoji.module_base.util.DictUtils import dev.utils.app.info.KeyValue import kotlinx.coroutines.launch @@ -39,6 +40,109 @@ class IntImpStorageUseViewModel : BasePageViewModel() { val totalPc = MutableLiveData("0") // 总件数 val totalWeight = MutableLiveData("0") // 总重量 + // ========== 5.5寸手机版专属 ========== + // 搜索框统一入口(placeholder「搜索运单号/航班号」,phoneSearchClick 分流) + val phoneSearchKey = MutableLiveData("") + + // 筛选弹层显隐 + val filterVisible = MutableLiveData(false) + + // 筛选条件(fdep 为接口入参;其余 5 项为后端未定义入参,预留传参,见接口问题清单 #25) + val fdep = MutableLiveData("") // 始发站 + val agentId = MutableLiveData("") // 代理(agentCode,预留) + val spCode = MutableLiveData("") // 特码(预留) + val awbType = MutableLiveData("") // 运单类型(预留) + val businessType = MutableLiveData("") // 业务类型(预留) + val goodsCn = MutableLiveData("") // 品名(中)(预留) + + // 筛选下拉字典(initPhoneExtras 加载,平板不请求) + val agentList = MutableLiveData(listOf(KeyValue("全部", ""))) + val specialCodeList = MutableLiveData>(emptyList()) + val awbTypeList = MutableLiveData>(emptyList()) + val businessTypeList = MutableLiveData( + listOf( + KeyValue("全部", ""), + KeyValue("普货", "1"), + KeyValue("特货", "2") + ) + ) + + // 三格统计:未清仓 / 已清仓(复用 pageQueryTotal 按 clearNormal=0/1 各查一次) + val unclearedCount = MutableLiveData("0") + val clearedCount = MutableLiveData("0") + + private var phoneExtrasEnabled = false + + /** + * 手机形态专属初始化(Activity 在 DeviceUtil.isPhone() 时调用)。 + * 平板端不调用,请求次数与行为零变化。 + */ + fun initPhoneExtras() { + phoneExtrasEnabled = true + // 代理(国际进港口径) + DictUtils.getIntImpAgentList(addAll = false) { list -> + agentList.postValue(listOf(KeyValue("全部", "")) + list) + } + // 特码:flag=1 国际;ieFlag 必须留空 + DictUtils.getSpecialCodeList(addAll = false, flag = 1, ieFlag = "") { list -> + specialCodeList.postValue(listOf(KeyValue("全部", "")) + list) + } + // 运单类型(type=II 国际进港) + DictUtils.getWaybillTypeList(type = Constant.businessType.II, addAll = true) { + awbTypeList.postValue(it) + } + } + + /** + * 手机搜索框查询:按出港计重实测规则分流——含字母→航班号,其余→运单号 + */ + fun phoneSearchClick() { + val key = phoneSearchKey.value?.trim() ?: "" + when { + key.isEmpty() -> { + wbNo.value = "" + flightNo.value = "" + } + key.any { it.isLetter() } -> { + flightNo.value = key + wbNo.value = "" + } + else -> { + wbNo.value = key + flightNo.value = "" + } + } + refresh() + } + + /** 筛选按钮点击 - 打开筛选面板 */ + fun filterClick() { + filterVisible.value = true + } + + /** 关闭筛选面板 */ + fun closeFilter() { + filterVisible.value = false + } + + /** 重置筛选条件 */ + fun resetFilter() { + flightDate.value = "" + flightNo.value = "" + fdep.value = "" + agentId.value = "" + spCode.value = "" + awbType.value = "" + businessType.value = "" + goodsCn.value = "" + } + + /** 确认筛选 - 关闭面板并刷新 */ + fun confirmFilter() { + filterVisible.value = false + refresh() + } + // ========== 全选状态 ========== val isAllChecked = MutableLiveData(false) @@ -250,12 +354,20 @@ class IntImpStorageUseViewModel : BasePageViewModel() { } override fun getData() { + // 手机专属 6 项平板恒为空,不进请求;agentCode/spCode/awbType/businessType/goodsCn + // 为 pageQuery 未定义入参(后端静默忽略,补齐后自动生效,见接口问题清单 #25) val filterParams = mapOf( "fdate" to flightDate.value?.ifEmpty { null }, "fno" to flightNo.value?.ifEmpty { null }, "wbNo" to wbNo.value?.ifEmpty { null }, "location" to location.value?.ifEmpty { null }, - "clearNormal" to clearResult.value?.ifEmpty { null } + "clearNormal" to clearResult.value?.ifEmpty { null }, + "fdep" to fdep.value?.ifEmpty { null }, + "agentCode" to agentId.value?.ifEmpty { null }, + "spCode" to spCode.value?.ifEmpty { null }, + "awbType" to awbType.value?.ifEmpty { null }, + "businessType" to businessType.value?.ifEmpty { null }, + "goodsCn" to goodsCn.value?.ifEmpty { null } ) val listParams = (filterParams + mapOf( @@ -281,5 +393,17 @@ class IntImpStorageUseViewModel : BasePageViewModel() { totalWeight.value = (data?.totalWeight ?: 0.0).toString() } } + + // 手机专属:未清仓/已清仓分项统计(同条件 + clearNormal=0/1 各查一次,平板不发) + if (phoneExtrasEnabled) { + val unclearedParams = (filterParams + mapOf("clearNormal" to "0")).toRequestBody() + launchCollect({ NetApply.api.getIntImpStorageUseTotal(unclearedParams) }) { + onSuccess = { unclearedCount.value = (it.data?.wbNumber ?: 0).toString() } + } + val clearedParams = (filterParams + mapOf("clearNormal" to "1")).toRequestBody() + launchCollect({ NetApply.api.getIntImpStorageUseTotal(clearedParams) }) { + onSuccess = { clearedCount.value = (it.data?.wbNumber ?: 0).toString() } + } + } } } diff --git a/module_gjj/src/main/res/layout-sw600dp/activity_int_imp_query_details.xml b/module_gjj/src/main/res/layout-sw600dp/activity_int_imp_query_details.xml new file mode 100644 index 0000000..ad3219c --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/activity_int_imp_query_details.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout-sw600dp/activity_int_imp_storage_use.xml b/module_gjj/src/main/res/layout-sw600dp/activity_int_imp_storage_use.xml new file mode 100644 index 0000000..1d0eab7 --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/activity_int_imp_storage_use.xml @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout-sw600dp/dialog_int_imp_in_storage.xml b/module_gjj/src/main/res/layout-sw600dp/dialog_int_imp_in_storage.xml new file mode 100644 index 0000000..2dba956 --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/dialog_int_imp_in_storage.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout-sw600dp/dialog_int_imp_modify_storage.xml b/module_gjj/src/main/res/layout-sw600dp/dialog_int_imp_modify_storage.xml new file mode 100644 index 0000000..d3bc331 --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/dialog_int_imp_modify_storage.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout-sw600dp/dialog_int_imp_move_clear.xml b/module_gjj/src/main/res/layout-sw600dp/dialog_int_imp_move_clear.xml new file mode 100644 index 0000000..52dc564 --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/dialog_int_imp_move_clear.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout-sw600dp/fragment_int_imp_query_storage.xml b/module_gjj/src/main/res/layout-sw600dp/fragment_int_imp_query_storage.xml new file mode 100644 index 0000000..6a02988 --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/fragment_int_imp_query_storage.xml @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout-sw600dp/fragment_int_imp_query_warehouse.xml b/module_gjj/src/main/res/layout-sw600dp/fragment_int_imp_query_warehouse.xml new file mode 100644 index 0000000..e2cd6b3 --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/fragment_int_imp_query_warehouse.xml @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout-sw600dp/fragment_int_imp_query_waybill.xml b/module_gjj/src/main/res/layout-sw600dp/fragment_int_imp_query_waybill.xml new file mode 100644 index 0000000..7f5dabd --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/fragment_int_imp_query_waybill.xml @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout-sw600dp/item_int_imp_query_storage.xml b/module_gjj/src/main/res/layout-sw600dp/item_int_imp_query_storage.xml new file mode 100644 index 0000000..7c6937f --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/item_int_imp_query_storage.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout-sw600dp/item_int_imp_query_warehouse.xml b/module_gjj/src/main/res/layout-sw600dp/item_int_imp_query_warehouse.xml new file mode 100644 index 0000000..8c45c70 --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/item_int_imp_query_warehouse.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout-sw600dp/item_int_imp_storage_use.xml b/module_gjj/src/main/res/layout-sw600dp/item_int_imp_storage_use.xml new file mode 100644 index 0000000..0045227 --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/item_int_imp_storage_use.xml @@ -0,0 +1,433 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/item_int_imp_storage_use_sub.xml b/module_gjj/src/main/res/layout-sw600dp/item_int_imp_storage_use_sub.xml similarity index 100% rename from module_gjj/src/main/res/layout/item_int_imp_storage_use_sub.xml rename to module_gjj/src/main/res/layout-sw600dp/item_int_imp_storage_use_sub.xml diff --git a/module_gjj/src/main/res/layout/activity_int_imp_query_details.xml b/module_gjj/src/main/res/layout/activity_int_imp_query_details.xml index ad3219c..2a14f83 100644 --- a/module_gjj/src/main/res/layout/activity_int_imp_query_details.xml +++ b/module_gjj/src/main/res/layout/activity_int_imp_query_details.xml @@ -1,6 +1,18 @@ - + + @@ -14,27 +26,25 @@ - - + + android:textColor="@{viewModel.currentTab == 0 ? @color/phone_primary : @color/phone_text_body}" + android:textSize="14sp" + android:textStyle="bold" /> + + android:textColor="@{viewModel.currentTab == 1 ? @color/phone_primary : @color/phone_text_body}" + android:textSize="14sp" + android:textStyle="bold" /> + + android:textColor="@{viewModel.currentTab == 2 ? @color/phone_primary : @color/phone_text_body}" + android:textSize="14sp" + android:textStyle="bold" /> + + android:layout_height="1px" + android:background="@color/phone_divider" /> + - + - + + - + android:background="@color/phone_page_bg"> - - - + android:layout_height="match_parent" + android:orientation="vertical"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + hint='@{"请选择航班日期"}' + title='@{"航班日期"}' + type="@{PhoneDataLayoutType.DATE}" + value="@={viewModel.flightDate}" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + hint='@{"请输入航班号"}' + title='@{"航班号"}' + type="@{PhoneDataLayoutType.INPUT}" + value="@={viewModel.flightNo}" /> - - - - - - - - + + hint='@{"请选择代理"}' + list="@{viewModel.agentList}" + title='@{"代理"}' + type="@{PhoneDataLayoutType.SPINNER}" + value="@={viewModel.agentId}" /> - - - - - - - - - - + + hint='@{"请选择特码"}' + list="@{viewModel.specialCodeList}" + title='@{"特码"}' + type="@{PhoneDataLayoutType.SPINNER}" + value="@={viewModel.spCode}" /> - - + + - - + + - - + + - - + + - + - - - + diff --git a/module_gjj/src/main/res/layout/dialog_int_imp_in_storage.xml b/module_gjj/src/main/res/layout/dialog_int_imp_in_storage.xml index 2dba956..048e833 100644 --- a/module_gjj/src/main/res/layout/dialog_int_imp_in_storage.xml +++ b/module_gjj/src/main/res/layout/dialog_int_imp_in_storage.xml @@ -1,8 +1,13 @@ + - + + android:background="@drawable/bg_phone_panel_top" + android:orientation="vertical" + android:paddingHorizontal="20dp" + android:paddingTop="24dp" + android:paddingBottom="32dp"> - - - - - + + android:layout_marginBottom="24dp"> - - + android:gravity="center" + android:text="入库操作" + android:textColor="@color/phone_text_strong" + android:textSize="18sp" + android:textStyle="bold" /> - + - + - - - - - - + + hint='@{"请选择库位"}' + list="@{model.locationList}" + title='@{"库位号"}' + type="@{PhoneDataLayoutType.SPINNER}" + value="@={model.selectedLocationCode}" /> - - - - - + + diff --git a/module_gjj/src/main/res/layout/dialog_int_imp_modify_storage.xml b/module_gjj/src/main/res/layout/dialog_int_imp_modify_storage.xml index d3bc331..9151ebf 100644 --- a/module_gjj/src/main/res/layout/dialog_int_imp_modify_storage.xml +++ b/module_gjj/src/main/res/layout/dialog_int_imp_modify_storage.xml @@ -1,8 +1,14 @@ + - + + android:background="@drawable/bg_phone_panel_top" + android:orientation="vertical" + android:paddingHorizontal="20dp" + android:paddingTop="24dp" + android:paddingBottom="32dp"> - - - - - + + android:layout_marginBottom="24dp"> - - + android:gravity="center" + android:text="修改库位" + android:textColor="@color/phone_text_strong" + android:textSize="18sp" + android:textStyle="bold" /> - + - + - - - - - - + + hint='@{"请选择原库位"}' + list="@{model.sourceList}" + title='@{"原库位"}' + type="@{PhoneDataLayoutType.SPINNER}" + value="@={model.selectedSourceId}" /> - + + - - - + + diff --git a/module_gjj/src/main/res/layout/dialog_int_imp_move_clear.xml b/module_gjj/src/main/res/layout/dialog_int_imp_move_clear.xml index 52dc564..b9baf23 100644 --- a/module_gjj/src/main/res/layout/dialog_int_imp_move_clear.xml +++ b/module_gjj/src/main/res/layout/dialog_int_imp_move_clear.xml @@ -1,8 +1,13 @@ + - + + android:background="@drawable/bg_phone_panel_top" + android:orientation="vertical" + android:paddingHorizontal="20dp" + android:paddingTop="24dp" + android:paddingBottom="32dp"> - - - - - + + android:layout_marginBottom="24dp"> - - + android:gravity="center" + android:text="清仓操作" + android:textColor="@color/phone_text_strong" + android:textSize="18sp" + android:textStyle="bold" /> - + - + - - - - - - + + hint='@{"请选择清仓正常"}' + list="@{model.clearNormalList}" + title='@{"清仓正常"}' + type="@{PhoneDataLayoutType.SPINNER}" + value="@={model.clearNormal}" /> - - - - - + + diff --git a/module_gjj/src/main/res/layout/fragment_int_imp_query_storage.xml b/module_gjj/src/main/res/layout/fragment_int_imp_query_storage.xml index 6a02988..77a821b 100644 --- a/module_gjj/src/main/res/layout/fragment_int_imp_query_storage.xml +++ b/module_gjj/src/main/res/layout/fragment_int_imp_query_storage.xml @@ -1,4 +1,14 @@ + @@ -7,130 +17,37 @@ - + android:background="@color/phone_page_bg"> - + android:clipToPadding="false" + android:overScrollMode="never" + android:paddingBottom="16dp" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" /> - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + diff --git a/module_gjj/src/main/res/layout/fragment_int_imp_query_warehouse.xml b/module_gjj/src/main/res/layout/fragment_int_imp_query_warehouse.xml index e2cd6b3..f9cf2fb 100644 --- a/module_gjj/src/main/res/layout/fragment_int_imp_query_warehouse.xml +++ b/module_gjj/src/main/res/layout/fragment_int_imp_query_warehouse.xml @@ -1,4 +1,14 @@ + @@ -7,140 +17,37 @@ - + android:background="@color/phone_page_bg"> - + android:clipToPadding="false" + android:overScrollMode="never" + android:paddingBottom="16dp" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" /> - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + diff --git a/module_gjj/src/main/res/layout/fragment_int_imp_query_waybill.xml b/module_gjj/src/main/res/layout/fragment_int_imp_query_waybill.xml index 7f5dabd..0bd2ca5 100644 --- a/module_gjj/src/main/res/layout/fragment_int_imp_query_waybill.xml +++ b/module_gjj/src/main/res/layout/fragment_int_imp_query_waybill.xml @@ -1,9 +1,24 @@ + - - + @@ -12,322 +27,395 @@ + android:background="@color/phone_page_bg" + android:fillViewport="true" + android:overScrollMode="never"> + android:padding="12dp"> - + + android:paddingHorizontal="14dp" + android:paddingBottom="14dp"> - + + + + + + + + + + + + - + value='@{viewModel.str(viewModel.maWbData, "wbNo")}' /> - + value='@{viewModel.strOr(viewModel.maWbData, "agentName", "agentCode")}' /> - + + + + + + value='@{viewModel.str(viewModel.maWbData, "spCode")}' /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + value='@{viewModel.strOr(viewModel.maWbData, "by1", "by0")}' /> - + - + title='@{"始发站"}' + value='@{viewModel.str(viewModel.maWbData, "dep")}' /> - + + + + + + + + + + value='@{viewModel.str(viewModel.maWbData, "unNumber")}' /> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + android:gravity="center_vertical" + android:orientation="horizontal" + android:paddingVertical="12dp"> - + - + android:layout_marginStart="8dp" + android:text="回执信息" + android:textColor="@color/phone_text_title" + android:textSize="15sp" + android:textStyle="bold" /> - + + + - - - - - - - - - - + value='@{viewModel.str(viewModel.maWbData, "mftStatus")}' /> - + value='@{viewModel.str(viewModel.maWbData, "tallyStatus")}' /> - + value='@{viewModel.str(viewModel.maWbData, "command")}' /> - - - diff --git a/module_gjj/src/main/res/layout/item_int_imp_query_storage.xml b/module_gjj/src/main/res/layout/item_int_imp_query_storage.xml index 7c6937f..c73b07d 100644 --- a/module_gjj/src/main/res/layout/item_int_imp_query_storage.xml +++ b/module_gjj/src/main/res/layout/item_int_imp_query_storage.xml @@ -1,5 +1,16 @@ - + + @@ -15,85 +26,88 @@ + android:layout_marginHorizontal="12dp" + android:layout_marginTop="12dp" + android:background="@drawable/bg_phone_card" + android:orientation="vertical" + android:paddingHorizontal="14dp" + android:paddingBottom="14dp"> + + android:paddingVertical="12dp"> - - + - - - - - - - - - - - - - - + - - + android:layout_marginBottom="12dp" + android:background="@color/phone_divider" /> + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/item_int_imp_query_warehouse.xml b/module_gjj/src/main/res/layout/item_int_imp_query_warehouse.xml index 8c45c70..044195a 100644 --- a/module_gjj/src/main/res/layout/item_int_imp_query_warehouse.xml +++ b/module_gjj/src/main/res/layout/item_int_imp_query_warehouse.xml @@ -1,5 +1,16 @@ - + + @@ -15,95 +26,111 @@ + android:layout_marginHorizontal="12dp" + android:layout_marginTop="12dp" + android:background="@drawable/bg_phone_card" + android:orientation="vertical" + android:paddingHorizontal="14dp" + android:paddingBottom="14dp"> + + android:paddingVertical="12dp"> - - + - - - - - - - - - - - - - - - - - + - - + android:layout_marginBottom="12dp" + android:background="@color/phone_divider" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/item_int_imp_storage_use.xml b/module_gjj/src/main/res/layout/item_int_imp_storage_use.xml index 0045227..c603527 100644 --- a/module_gjj/src/main/res/layout/item_int_imp_storage_use.xml +++ b/module_gjj/src/main/res/layout/item_int_imp_storage_use.xml @@ -1,7 +1,23 @@ + + xmlns:tools="http://schemas.android.com/tools"> @@ -16,418 +32,243 @@ type="Integer" /> - - + android:layout_marginHorizontal="16dp" + android:layout_marginTop="12dp" + android:background="@drawable/bg_phone_card" + android:orientation="vertical" + android:padding="14dp"> - + + android:gravity="center_vertical" + android:orientation="horizontal"> - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + android:paddingHorizontal="8dp" + android:text="已清仓" + android:textColor="@color/phone_tag_green_text" + android:textSize="11sp" + android:visibility="@{bean.isCleared ? View.VISIBLE : View.GONE}" /> - - + + - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 dfbba7b..41412d8 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 @@ -66,6 +66,18 @@ class GjViewModel : BaseViewModel() { Constant.AuthName.GjcQueryListActivity, ARouterConstants.ACTIVITY_URL_GJC_QUERY_LIST ), + ActionBean( + "出港仓库", + R.drawable.gjc_cang_ku_icon, + Constant.AuthName.GjcIntExpStorageUse, + ARouterConstants.ACTIVITY_URL_INT_EXP_STORAGE_USE + ), + ActionBean( + "进港仓库", + R.drawable.gjc_cang_ku_icon, // Pad 端进港仓库菜单同样复用出港仓库图标 + Constant.AuthName.GjjWareHouseActivity, + ARouterConstants.ACTIVITY_URL_GJJ_WARE_HOUSE + ), // ULD管理属综合管理业务(Pad 端在「综合管理」菜单组),手机端首页暂无综合 Tab,挂在国际 Tab 下 ActionBean( "ULD管理", diff --git a/module_p/src/main/res/drawable-xxhdpi/gjc_cang_ku_icon.png b/module_p/src/main/res/drawable-xxhdpi/gjc_cang_ku_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6dceea0e9d19cf464c3e775e1b0ae30599c4431f GIT binary patch literal 32161 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 HIEMTm5gq|) literal 0 HcmV?d00001