From db062c8ee36b8af2b9b04506af9ffad4f71cf7b8 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Wed, 29 Jul 2026 14:18:29 +0800 Subject: [PATCH 01/29] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=9B=BD?= =?UTF-8?q?=E9=99=85=E5=87=BA=E6=B8=AF=E7=A7=BB=E5=BA=93/=E5=87=BA?= =?UTF-8?q?=E5=BA=93=E4=BA=A4=E6=8E=A5=E9=A1=B5=E9=9D=A25.5=E5=AF=B8?= =?UTF-8?q?=E6=89=8B=E6=9C=BA=E7=AB=AF=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 落地手机端双形态适配框架:同名布局+资源限定符(layout/手机、 layout-sw600dp/平板)自动切换,DeviceUtil 设备形态判定,7个 手机版公共组件(PhoneSearchBar/StatusTab/DataLayout/FilterPanel/ BottomBar/StatBox/KvItem) - 完成「国际出港移库」「国际出港出库交接」两页手机端适配,新增 各自详情页(IntExpMoveDetailActivity/IntExpOutHandoverDetailActivity) - 手机端首页菜单接入"出港移库""出库交接"入口 - 修复手机端进入页面先横屏后转竖屏的闪屏问题:Manifest 全项目 192 处改为 screenOrientation="unspecified",由 BaseActivity 按设备形态运行时锁定方向 - 修复该方案的中间版本在平板端引入的回归(先竖后横 + UI放大1.6倍) - AutoSize 补充手机竖屏 390×844 设计基准 - 修复 CHANGELOG.md 因脚本异常导致的内容重复损坏(膨胀至12万行), 恢复正常结构并补充本次变更记录 Co-Authored-By: Claude Sonnet 5 --- .claude/mcp.json | 14 +- .claude/skills/phone-adapt/SKILL.md | 277 ++++ .../phone-adapt/references/components.md | 120 ++ .../phone-adapt/references/pad-safety.md | 167 +++ .../phone-adapt/references/verification.md | 166 +++ .../phone-adapt/scripts/design_shots.py | 137 ++ .../skills/phone-adapt/scripts/ui_probe.sh | 119 ++ CHANGELOG.md | 223 ++-- CLAUDE.md | 307 ++++- README.md | 627 ++++----- app/src/debug/AndroidManifest.xml | 42 + app/src/main/AndroidManifest.xml | 1154 +++++++++-------- documents/5.5寸手持端-后端字段补充清单.md | 55 + .../5.5寸手持端设计文件/00_全部入口总览.html | 195 +++ .../01_ULD管理/ULD管理.html | 650 ++++++++++ .../02_出库交接/出库交接.html | 715 ++++++++++ .../03_出港计重/detail.html | 151 +++ .../5.5寸手持端设计文件/03_出港计重/main.html | 419 ++++++ .../03_出港计重/records.html | 282 ++++ .../03_出港计重/weighing.html | 256 ++++ .../03_出港计重/weight-detail.html | 306 +++++ .../5.5寸手持端设计文件/04_出港运抵/main.html | 535 ++++++++ .../04_出港运抵/receipt.html | 73 ++ .../04_出港运抵/suborder.html | 413 ++++++ .../04_出港运抵/supplement.html | 175 +++ .../05_出港移库/出港移库.html | 668 ++++++++++ .../06_出港查询/出港查询.html | 963 ++++++++++++++ .../06_出港查询/运单追踪.html | 139 ++ .../07_出港仓库/出港仓库.html | 932 +++++++++++++ .../07_出港仓库/运单追踪.html | 139 ++ .../08_进港仓库/运单追踪.html | 139 ++ .../08_进港仓库/进港仓库.html | 924 +++++++++++++ .../09_提取出库/提取出库.html | 773 +++++++++++ .../10_进港查询/运单追踪.html | 147 +++ .../10_进港查询/进港查询.html | 951 ++++++++++++++ .../11_进港移库/photo.html | 134 ++ .../11_进港移库/进港移库.html | 831 ++++++++++++ documents/5.5寸手持端适配技术方案.md | 312 +++++ ...º货运APP-5.5寸手持端UI适配-工时报价明细.xlsx | Bin 0 -> 17364 bytes ...ª空货运APP-5.5寸手持端适配报价单(对外).xlsx | Bin 0 -> 7521 bytes .../航空货运APP-5.5寸手持端适配报价单.xlsx | Bin 0 -> 11067 bytes .../长卿科技-航空货运作业管理系统报价.xlsx | Bin 0 -> 13433 bytes .../src/main/debug/AndroidManifest.xml | 64 +- .../lukouguoji/module_base/BaseActivity.kt | 39 +- .../lukouguoji/module_base/MyApplication.kt | 21 +- .../module_base/base/BaseBindingActivity.kt | 15 +- .../lukouguoji/module_base/bean/ActionBean.kt | 27 +- .../lukouguoji/module_base/bean/GjcMove.kt | 17 + .../module_base/bean/GjcUldUseBean.kt | 15 + .../ui/weight/phone/PhoneBottomBar.kt | 92 ++ .../ui/weight/phone/PhoneDataLayout.kt | 238 ++++ .../ui/weight/phone/PhoneFilterPanel.kt | 120 ++ .../ui/weight/phone/PhoneKvItem.kt | 100 ++ .../ui/weight/phone/PhoneSearchBar.kt | 139 ++ .../ui/weight/phone/PhoneStatBox.kt | 108 ++ .../ui/weight/phone/PhoneStatusTab.kt | 168 +++ .../ui/weight/phone/PhoneWidgetKtx.kt | 228 ++++ .../lukouguoji/module_base/util/DeviceUtil.kt | 116 ++ .../src/main/release/AndroidManifest.xml | 90 +- .../src/main/res/drawable/bg_phone_badge.xml | 7 + .../res/drawable/bg_phone_btn_outline.xml | 22 + .../res/drawable/bg_phone_btn_primary.xml | 16 + .../src/main/res/drawable/bg_phone_card.xml | 10 + .../drawable/bg_phone_card_header_blue.xml | 9 + .../drawable/bg_phone_card_header_green.xml | 9 + .../main/res/drawable/bg_phone_dot_green.xml | 6 + .../main/res/drawable/bg_phone_icon_round.xml | 9 + .../src/main/res/drawable/bg_phone_input.xml | 10 + .../main/res/drawable/bg_phone_panel_top.xml | 9 + .../src/main/res/drawable/bg_phone_search.xml | 10 + .../main/res/drawable/bg_phone_stat_box.xml | 7 + .../main/res/drawable/bg_phone_tag_gray.xml | 7 + .../main/res/drawable/bg_phone_tag_green.xml | 7 + .../main/res/drawable/bg_phone_tag_orange.xml | 11 + .../main/res/drawable/bg_phone_tag_red.xml | 7 + .../res/drawable/bg_phone_value_orange.xml | 11 + .../main/res/drawable/ic_phone_airplane.xml | 12 + .../main/res/drawable/ic_phone_calendar.xml | 12 + .../res/drawable/ic_phone_check_circle.xml | 12 + .../drawable/ic_phone_check_round_checked.xml | 23 + .../ic_phone_check_round_unchecked.xml | 16 + .../res/drawable/ic_phone_chevron_down.xml | 12 + .../res/drawable/ic_phone_chevron_right.xml | 12 + .../src/main/res/drawable/ic_phone_close.xml | 12 + .../main/res/drawable/ic_phone_location.xml | 12 + .../src/main/res/drawable/ic_phone_person.xml | 12 + .../res/layout-sw600dp/title_tool_bar.xml | 42 + .../res/layout/item_spinner_list_14sp.xml | 15 + .../res/layout/layout_phone_bottom_bar.xml | 64 + .../res/layout/layout_phone_data_layout.xml | 94 ++ .../res/layout/layout_phone_filter_panel.xml | 87 ++ .../res/layout/layout_phone_search_bar.xml | 65 + .../main/res/layout/layout_phone_stat_box.xml | 138 ++ .../src/main/res/layout/title_tool_bar.xml | 109 +- module_base/src/main/res/values/colors.xml | 27 + module_cargo/src/main/AndroidManifest.xml | 20 +- .../src/main/debug/AndroidManifest.xml | 48 +- .../src/main/release/AndroidManifest.xml | 32 +- module_gjc/src/main/debug/AndroidManifest.xml | 48 +- .../gjc/activity/IntExpOutHandoverActivity.kt | 152 ++- .../IntExpOutHandoverDetailActivity.kt | 40 + .../gjc/holder/IntExpMoveViewHolder.kt | 6 + .../gjc/holder/IntExpOutHandoverViewHolder.kt | 69 +- .../gjc/page/move/IntExpMoveActivity.kt | 66 +- .../gjc/page/move/IntExpMoveDetailActivity.kt | 40 + .../viewModel/IntExpMoveDetailViewModel.kt | 25 + .../gjc/viewModel/IntExpMoveViewModel.kt | 74 +- .../IntExpOutHandoverDetailViewModel.kt | 25 + .../viewModel/IntExpOutHandoverViewModel.kt | 100 +- .../src/main/release/AndroidManifest.xml | 162 +-- .../layout-sw600dp/activity_int_exp_move.xml | 206 +++ .../activity_int_exp_out_handover.xml | 197 +++ .../res/layout-sw600dp/item_int_exp_move.xml | 319 +++++ .../item_int_exp_out_handover.xml | 300 +++++ .../main/res/layout/activity_int_exp_move.xml | 374 +++--- .../layout/activity_int_exp_move_detail.xml | 268 ++++ .../layout/activity_int_exp_out_handover.xml | 354 +++-- .../activity_int_exp_out_handover_detail.xml | 263 ++++ .../src/main/res/layout/item_int_exp_move.xml | 521 +++----- .../res/layout/item_int_exp_out_handover.xml | 525 ++++---- module_gjj/src/main/debug/AndroidManifest.xml | 48 +- .../src/main/release/AndroidManifest.xml | 196 +-- module_gnc/src/main/debug/AndroidManifest.xml | 48 +- .../src/main/release/AndroidManifest.xml | 196 +-- module_gnj/src/main/AndroidManifest.xml | 52 +- module_gnj/src/main/debug/AndroidManifest.xml | 86 +- .../src/main/release/AndroidManifest.xml | 170 +-- .../src/main/debug/AndroidManifest.xml | 48 +- .../src/main/release/AndroidManifest.xml | 54 +- module_mit/src/main/debug/AndroidManifest.xml | 48 +- .../src/main/release/AndroidManifest.xml | 84 +- .../sixin/module_p/ui/enter/gj/GjViewModel.kt | 133 +- .../res/drawable-xxhdpi/gjc_yi_ku_icon.png | Bin 0 -> 32732 bytes .../drawable-xxhdpi/img_gjc_chuku_jiaojie.png | Bin 0 -> 32239 bytes 134 files changed, 19602 insertions(+), 2965 deletions(-) create mode 100644 .claude/skills/phone-adapt/SKILL.md create mode 100644 .claude/skills/phone-adapt/references/components.md create mode 100644 .claude/skills/phone-adapt/references/pad-safety.md create mode 100644 .claude/skills/phone-adapt/references/verification.md create mode 100755 .claude/skills/phone-adapt/scripts/design_shots.py create mode 100755 .claude/skills/phone-adapt/scripts/ui_probe.sh create mode 100644 app/src/debug/AndroidManifest.xml create mode 100644 documents/5.5寸手持端-后端字段补充清单.md create mode 100644 documents/5.5寸手持端设计文件/00_全部入口总览.html create mode 100644 documents/5.5寸手持端设计文件/01_ULD管理/ULD管理.html create mode 100644 documents/5.5寸手持端设计文件/02_出库交接/出库交接.html create mode 100644 documents/5.5寸手持端设计文件/03_出港计重/detail.html create mode 100644 documents/5.5寸手持端设计文件/03_出港计重/main.html create mode 100644 documents/5.5寸手持端设计文件/03_出港计重/records.html create mode 100644 documents/5.5寸手持端设计文件/03_出港计重/weighing.html create mode 100644 documents/5.5寸手持端设计文件/03_出港计重/weight-detail.html create mode 100644 documents/5.5寸手持端设计文件/04_出港运抵/main.html create mode 100644 documents/5.5寸手持端设计文件/04_出港运抵/receipt.html create mode 100644 documents/5.5寸手持端设计文件/04_出港运抵/suborder.html create mode 100644 documents/5.5寸手持端设计文件/04_出港运抵/supplement.html create mode 100644 documents/5.5寸手持端设计文件/05_出港移库/出港移库.html create mode 100644 documents/5.5寸手持端设计文件/06_出港查询/出港查询.html create mode 100644 documents/5.5寸手持端设计文件/06_出港查询/运单追踪.html create mode 100644 documents/5.5寸手持端设计文件/07_出港仓库/出港仓库.html create mode 100644 documents/5.5寸手持端设计文件/07_出港仓库/运单追踪.html create mode 100644 documents/5.5寸手持端设计文件/08_进港仓库/运单追踪.html create mode 100644 documents/5.5寸手持端设计文件/08_进港仓库/进港仓库.html create mode 100644 documents/5.5寸手持端设计文件/09_提取出库/提取出库.html create mode 100644 documents/5.5寸手持端设计文件/10_进港查询/运单追踪.html create mode 100644 documents/5.5寸手持端设计文件/10_进港查询/进港查询.html create mode 100644 documents/5.5寸手持端设计文件/11_进港移库/photo.html create mode 100644 documents/5.5寸手持端设计文件/11_进港移库/进港移库.html create mode 100644 documents/5.5寸手持端适配技术方案.md create mode 100644 documents/航空货运APP-5.5寸手持端UI适配-工时报价明细.xlsx create mode 100644 documents/航空货运APP-5.5寸手持端适配报价单(对外).xlsx create mode 100644 documents/航空货运APP-5.5寸手持端适配报价单.xlsx create mode 100644 documents/长卿科技-航空货运作业管理系统报价.xlsx create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneBottomBar.kt create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneDataLayout.kt create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFilterPanel.kt create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneKvItem.kt create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneSearchBar.kt create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneStatBox.kt create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneStatusTab.kt create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneWidgetKtx.kt create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/util/DeviceUtil.kt create mode 100644 module_base/src/main/res/drawable/bg_phone_badge.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_btn_outline.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_btn_primary.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_card.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_card_header_blue.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_card_header_green.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_dot_green.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_icon_round.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_input.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_panel_top.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_search.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_stat_box.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_tag_gray.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_tag_green.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_tag_orange.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_tag_red.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_value_orange.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_airplane.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_calendar.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_check_circle.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_check_round_checked.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_check_round_unchecked.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_chevron_down.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_chevron_right.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_close.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_location.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_person.xml create mode 100644 module_base/src/main/res/layout-sw600dp/title_tool_bar.xml create mode 100644 module_base/src/main/res/layout/item_spinner_list_14sp.xml create mode 100644 module_base/src/main/res/layout/layout_phone_bottom_bar.xml create mode 100644 module_base/src/main/res/layout/layout_phone_data_layout.xml create mode 100644 module_base/src/main/res/layout/layout_phone_filter_panel.xml create mode 100644 module_base/src/main/res/layout/layout_phone_search_bar.xml create mode 100644 module_base/src/main/res/layout/layout_phone_stat_box.xml create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverDetailActivity.kt create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveDetailActivity.kt create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveDetailViewModel.kt create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverDetailViewModel.kt create mode 100644 module_gjc/src/main/res/layout-sw600dp/activity_int_exp_move.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/activity_int_exp_out_handover.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/item_int_exp_move.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/item_int_exp_out_handover.xml create mode 100644 module_gjc/src/main/res/layout/activity_int_exp_move_detail.xml create mode 100644 module_gjc/src/main/res/layout/activity_int_exp_out_handover_detail.xml create mode 100644 module_p/src/main/res/drawable-xxhdpi/gjc_yi_ku_icon.png create mode 100644 module_p/src/main/res/drawable-xxhdpi/img_gjc_chuku_jiaojie.png diff --git a/.claude/mcp.json b/.claude/mcp.json index 9270fdd..e5ee220 100644 --- a/.claude/mcp.json +++ b/.claude/mcp.json @@ -1,14 +1,10 @@ { "mcpServers": { - "空港集团 - API 文档": { - "command": "/Users/kid/.version-fox/sdks/nodejs/bin/npx", - "args": [ - "-y", - "apifox-mcp-server@latest", - "--project-id=7382863" - ], - "env": { - "APIFOX_ACCESS_TOKEN": "APS-S2aVVwqasbdByzPLgSqryRC8BB0ZFqhQ" + "api-doc": { + "type": "http", + "url": "https://www.agentfoxapp.com/mcp/976caff7-5f98-4487-bccf-3aa20c92cf1f", + "headers": { + "Authorization": "Bearer afk_G_VKmHTdXUi3GjQdg5AeHeH-0BSYQEPP" } } } diff --git a/.claude/skills/phone-adapt/SKILL.md b/.claude/skills/phone-adapt/SKILL.md new file mode 100644 index 0000000..011853a --- /dev/null +++ b/.claude/skills/phone-adapt/SKILL.md @@ -0,0 +1,277 @@ +--- +name: phone-adapt +description: 参照 documents/5.5寸手持端设计文件/ 的 HTML 设计稿,把 AirLogistics 指定页面适配成 5.5 寸手机竖屏版本——浏览器渲染设计稿逐态截图分析、复用 Phone* 公共组件写手机布局、复用现有 ViewModel 与接口、保证 Pad 端零改动,最后走完整登录流程实机联调并与设计稿逐项核对 UI。当用户说"适配手机端/做手机版/手持端适配"、点名某个设计稿入口(如"02 出库交接"、"做一下出港计重")、要求"按设计稿还原页面"、或提到 5.5 寸/手机版/双形态时,都要使用本 skill,即使没明说"适配"二字。 +--- + +# 5.5 寸手持端页面适配 + +把一个已有的平板页面,按设计稿适配出手机竖屏版本。核心约束是**只重写布局,业务逻辑与接口全部复用**, +Pad 端行为必须零变化。 + +先读 `CLAUDE.md` 的「5.5 寸手持端(手机版)双形态适配规范」章节——那里是权威规范,本 skill 是执行流程。 + +## 前置确认 + +需要用户给出**目标页面**(设计稿目录名或业务名,如「02 出库交接」/「出港计重」)。 +其余自己查:`documents/5.5寸手持端设计文件/00_全部入口总览.html` 列出全部 11 个入口, +每个子目录下可能有多个 HTML(主页 + 详情 + 子页面),都要处理。 + +对应的平板页面靠业务名在 `module_gjc/gjj/gnc/gnj` 里搜 Activity。**注意认准首页菜单实际跳转的那个 +Activity**,同名旧版文件在这个仓库里很常见。 + +## 阶段 1:渲染设计稿,看图不看代码 + +设计稿是带 Tailwind + JS 的交互原型,一个 HTML 里常塞了列表页、Tab、详情页、筛选弹层,靠 JS 切换。 + +**只读 HTML 源码会出错**,必须渲染成图: + +```bash +S=.claude/skills/phone-adapt/scripts +# 1) 先看有哪些状态可切 +python3 $S/design_shots.py --html "documents/5.5寸手持端设计文件/02_出库交接/出库交接.html" --list + +# 2) 按 --list 结果逐态渲染(照抄 onclick 里的真实参数最省事) +python3 $S/design_shots.py --html "…/出库交接.html" --out /tmp/design \ + --state "01_列表:" \ + --state "02_已交接Tab:switchTab('shipped');" \ + --state "03_详情:showDetail({id:'PMC90901CZ',status:'已交接',rackNo:'076'});" \ + --state "04_筛选弹层:toggleFilterDrawer(true);" +``` + +然后用 Read 工具**逐张看图**,抽取:配色、字号、圆角、间距、图标、控件顺序、空态、 +各状态下哪些元素显示/隐藏(例如「已交接」Tab 下底部操作条整条消失)。 + +`--list` 输出里如果出现 `window.location.href='xxx.html'`,说明是多文件原型,那些文件同样要渲染。 + +**设计稿的 JS 可能有 bug,别照抄字段映射。** 出库交接的详情页就把「航班日期」绑成了重量、 +「备注」绑成了航班号(HTML 里 id 重复)。判断依据是**静态 label 文案**:label 写「航班日期」 +就绑 `fdate`,写「板型」就绑 `boardType`。label 是设计意图,JS 只是 demo 接线。 + +标签文案同理:卡片上写死的「IMP代码」是占位符,实际要绑 `bean.dgrCode` 的值。 + +## 阶段 2:对齐接口能力,不要臆想 + +把设计稿的每个筛选项/Tab/字段,对照平板 ViewModel 已有的字段: + +- **已有字段** → 直接复用(如出港移库的 Tab 直接绑既有 `moveState`) +- **平板没有的新维度**(新 Tab 状态、新下拉、新排序)→ **停下来问用户**要用什么接口参数名, + 连带问数据源(如「交接人」用 `DictUtils.getWHSUserList()`) + +这一步不能猜。出库交接就是实测发现后端 `pageQuery` 根本不认 `hoState`,两个 Tab 返回同一批数据—— +参数名对不对只有后端知道。用 `AskUserQuestion` 一次问清,并在阶段 5 用真实请求体验证是否生效; +**没生效就在交付说明里如实标注**,不要让它看起来是通的。 + +### 开工前对齐方案 + +分析完先把结论摊给用户,避免闷头做错方向。一次说清,别挤牙膏: + +``` +📱 页面适配方案:<页面名> + +设计稿:documents/5.5寸手持端设计文件/<目录>/(N 个 HTML:主页 / 详情 / …) +平板页面:XxxActivity + XxxViewModel(module_xxx) + +手机版结构: + 搜索行:<字段>(含扫码/筛选按钮) + 状态 Tab: / → 绑定 <字段名> + 列表卡片:<字段…>,两种形态(<形态A> / <形态B>) + 底部操作条:全选 + 已选统计 + [<按钮>] + 筛选弹层:<字段1> / <字段2> / <字段3> + 二级页:<详情页名>(新增 Activity / 复用已有) + +复用组件:PhoneSearchBar、PhoneStatusTab、PhoneStatBox…(无需新增 / 需新增 XXX) + +接口:列表 <接口> 复用;新增参数 <名>(待你确认);新增字典 +Pad 端影响:无(新字段默认空、额外请求由手机开关控制) + +设计稿与平板的差异:<如手机版无「配运」按钮> + +确认后开始编码。 +``` + +## 阶段 3:写布局,复用公共组件 + +`module_base/.../ui/weight/phone/` 已有 7 个组件,**优先复用,不要重写 XML**。 +组件清单、属性表与用法见 `references/components.md`(写布局前读一遍)。 + +改造步骤: + +1. 平板布局 `git mv` 到 `res/layout-sw600dp/`(item 布局同理) +2. 在 `res/layout/` 下建**同名**文件写手机布局 +3. Kotlin 侧 `layoutId()` / `itemLayoutId` **一律不动**,不做设备分支 + +三条硬约束(违反会编译失败或运行时崩溃,细节见 `references/pad-safety.md`): + +| 约束 | 说明 | +|------|------| +| 两变体 `` 完全一致 | 手机变体新增 `activity` 变量时,平板变体也要补上(写注释说明平板不用它) | +| 共用 id 双方都要有 | ViewHolder/Activity 引用的 id(`srl`/`rv`/`iv_icon` 等)两边都保留 | +| 单侧独有 id 自动 `@Nullable` | 如手机独有的 `ll_detail`,ViewHolder 里必须判空调用 | + +**一套 item 布局覆盖多种卡片形态**,不要为「待交接/已交接」建两个布局。按 bean 状态切 +visibility 即可(Bean 上加个只读计算属性如 `isHandovered` 让 XML 更干净;计算属性不参与 Gson +序列化,安全)。 + +## 阶段 4:接业务,且不碰 Pad + +手机端新增的查询维度用这个模式,能做到平板端请求次数与行为零变化: + +```kotlin +// ViewModel:新字段默认空值,getData() 里仅非空才进请求 +val handoverState = MutableLiveData("") // 平板布局无对应控件 → 恒为空 → 不进请求 +val filterParams = mapOf( + /* 原有字段… */ + "hoState" to handoverState.value?.ifEmpty { null }, +) + +// 手机专属的额外请求(Tab 角标计数、新下拉字典)用内部开关控制 +private var phoneExtrasEnabled = false +fun initPhoneExtras() { phoneExtrasEnabled = true; handoverState.value = "0"; /* 加载字典 */ } +``` + +```kotlin +// Activity:只有手机形态才开启,平板不调用 +if (DeviceUtil.isPhone()) viewModel.initPhoneExtras() +``` + +设备判断只用于**数据默认值与额外请求**,**绝不用于选布局**(选布局靠资源限定符)。 + +纯 UI 交互(弹层显隐、Tab 切换)写在 Activity,用 `ObservableBoolean` 暴露给 XML,不下沉到 ViewModel。 + +设计稿若少了平板上的某个按钮(如出库交接手机版只有「交接」没有「配运」),按设计稿做, +但要在交付说明里点出来这个功能在手机端不可达,让用户决定。 + +新增手机专属页面(详情页等)记得:`app/src/main/AndroidManifest.xml` 注册 + +`app/src/debug/AndroidManifest.xml` 追加 `exported="true"` 便于直启调试。 + +注册时 `screenOrientation` **必须写 `unspecified`**: + +```xml + +``` + +- 写死 `userLandscape` → 手机端「先横屏、约 1 秒后转竖屏」闪一下(方向在建窗口时就定了,代码再纠正已晚) +- 用 `@integer/xxx` 资源引用 → **更糟**:系统解析 Manifest 不套用设备限定符,平板会取到默认(竖屏)值, + 先竖后横,且 AutoSize 随之选错基准导致 UI 放大约 1.6 倍 + +`unspecified` 让系统按设备当前物理方向建窗口,两端起始方向本就正确, +`BaseActivity` 的形态锁定不会产生二次纠正。 + +### ⚠️ 别忘了加手机端首页入口 + +手机端首页是 `module_p` 的 `PDAEnterActivity`,「国际」Tab 的菜单在 +`module_p/.../ui/enter/gj/GjViewModel.kt`(国内在 `gn/GnViewModel.kt`)。 +**菜单是手写清单,不是接口下发**;权限串只做过滤(`authList.contains(bean.key)`)。 + +适配完页面不回来加一行,手机上就**根本没有入口**——出库交接第一版就漏了这步, +只能靠 adb 直启才能进去。加法: + +```kotlin +ActionBean( + "出港移库", + R.drawable.gjc_yi_ku_icon, // 图标复用 Pad 同款,复制 PNG 到 module_p/res/drawable-xxhdpi/ + Constant.AuthName.GjcYiKuListActivity, // 权限串与 Pad 端菜单一致 + ARouterConstants.ACTIVITY_URL_INT_EXP_MOVE // 填了 route 就走通用跳转,无需 when 分支 +), +``` + +权限串和路由**都以 Pad 端 `app/.../HomeFragment.kt` 里该权限对应的 `ARouter.build(...)` 为准** +(同一业务常有新旧两个 Activity,Pad 菜单实际跳的才是要适配的那个)。 +`module_p` 只依赖 `module_base`,看不到业务模块,所以跨模块必须走 ARouter、图标必须复制一份。 + +菜单没出现时先分清是「没权限」还是「没加清单」: + +```bash +adb -s shell "run-as com.lukouguoji.aerologic \ + cat /data/data/com.lukouguoji.aerologic/shared_prefs/data.xml" | tr ',' '\n' | grep -oE "App[A-Za-z]+" | sort -u +``` + +## 阶段 5:端到端实机验证 + +先构建,再双端跑。命令与排障细节见 `references/verification.md`。 + +```bash +./gradlew assembleDebug 2>&1 | grep -E "^(BUILD|FAILURE)|error:" +``` + +构建过后核对 DataBinding 变体是否如预期(单侧 id 应为 `@Nullable`): + +```bash +grep -B3 "llDetail" module_gjc/build/generated/data_binding_base_class_source_out/debug/out/\ +com/lukouguoji/gjc/databinding/ItemXxxBinding.java +``` + +**手机端**(真实数据链路,从登录开始): + +```bash +P=.claude/skills/phone-adapt/scripts/ui_probe.sh +adb -s install -r -d app/build/outputs/apk/debug/app-debug.apk +# 走登录 → 底部「国际」Tab → 点新加的菜单项进入(顺便验证入口加对了) +# 同名文字多处时 tap-text 会提示命中数,用第 4 个参数指定序号(如底部 Tab 的「国际」) +# 若账号确实没有该权限,改用冷启动直启(见 verification.md) +$P form # 应打印 PHONE(sw=411dp…) +$P wait-text "待交接" # 点击前先等页面就绪:加载弹窗会吞掉点击 +$P tap-text "已交接" # 按文字点击,比手算坐标可靠 +$P texts # 用文字变化断言点击确实生效(如底部条应消失) +$P shot /tmp/p1.png +$P crash # 必须为 0 +$P req pageQuery # 核对请求体参数确实带上了新字段 +``` + +逐项走查:列表/卡片两种形态、详情页、筛选弹层(重置+确认)、Tab 切换、单选与全选联动、 +下拉真实取数、扫码入口。每步 `crash` 都要为 0。 + +点完**一定要断言效果**(`texts` 或截图),不要假设点中了——加载弹窗盖屏时 `input tap` 会被静默吞掉。 + +手机端还要确认方向没闪屏(冷启动采样 `mRotation` 应恒为 0),命令见 `references/verification.md`。 + +**Pad 端回归**(必做):同样安装到平板模拟器打开同一页面截图,与改造前逐项对比—— +搜索条数量、默认值、按钮、底部统计都应一致。改过 `module_base` 公共组件时这步尤其不能省。 + +## 阶段 6:与设计稿二次核对 + +把阶段 1 的设计稿截图和阶段 5 的实机截图放在一起,用 Read 工具对照看,逐项核对: + +配色 / 字号 / 字重 / 圆角 / 内外间距 / 图标形状与大小 / 控件顺序 / 选中态 / 状态标签配色 / +**空值兜底**(真实数据空字段很常见——出库交接就出现过「库位」为空时橙色高亮标签只剩一个孤零零的 +小色块,需要空值时不套标签底)。 + +服务端当天没数据时(列表空)先放宽条件重查;仍为空就临时在 Activity 里注入样例 Bean 截图比对: + +```kotlin +// import com.lukouguoji.module_base.ktx.commonAdapter +binding.rv.postDelayed({ + binding.rv.commonAdapter()?.refresh(listOf(/* 覆盖每种卡片形态各一条 */)) +}, 2500) // 等首次请求结束,否则会被真实结果覆盖 +``` + +**核对完必须删掉**,删完重新构建并 grep 确认无残留。 + +## 收尾:文档与交付说明 + +代码之外还要落三处文档,否则下一个人会重复踩坑: + +- 新增了公共组件/资源 → 更新 `CLAUDE.md`「手机版公共组件库」表 + `references/components.md` +- 踩到新坑(崩溃、静默失效、环境问题)→ 写进 `CLAUDE.md`「常见编译错误速查」和本 skill 的 + 对应 reference,把**定位手法**也写上,不只写结论 +- `CHANGELOG.md` 追加条目(新增 / 改进 / 修复 / 验证 四段),记忆文件 + `phone-5.5inch-adaptation.md` 同步 + +向用户汇报时明确写出这四块: + +1. 新增/修改的文件清单(布局、组件、Activity/ViewModel/Bean) +2. Pad 端零破坏的具体做法 + 回归结论 +3. 复用与新增的公共组件 +4. **待确认事项**:后端未生效的参数、自己推断的业务规则(如 IMP 代码红/绿的判定)、 + 设计稿与平板功能的差异。如实说,别含糊。 + +## 参考文件 + +- `references/components.md` — 7 个手机版公共组件的属性表、用法与封装新组件的规矩(写布局前读) +- `references/pad-safety.md` — 布局变体约束、Pad 零破坏模式、易崩点(写代码前读) +- `references/verification.md` — 双端 adb 命令、登录与直启、已知环境坑(验证前读) +- `scripts/design_shots.py` — 设计稿逐态渲染截图 +- `scripts/ui_probe.sh` — 实机取文字/按文字点击/等待/截图/抓请求体/查崩溃 diff --git a/.claude/skills/phone-adapt/references/components.md b/.claude/skills/phone-adapt/references/components.md new file mode 100644 index 0000000..e3a26a0 --- /dev/null +++ b/.claude/skills/phone-adapt/references/components.md @@ -0,0 +1,120 @@ +# 手机版公共组件(`module_base/.../ui/weight/phone/`) + +7 个组件覆盖设计稿反复出现的部件。**先复用,实在没有再新增**——每个新组件都要维护、都要踩一遍 +状态恢复的坑,能少一个是一个。 + +所有属性都是**无命名空间写法**(与平板端 `PadSearchLayout` 一致),DataBinding 适配器集中在 +`PhoneWidgetKtx.kt`。同名属性(`hint`/`value`/`title`/`list`)按控件类型解析,与 Pad 系组件不冲突。 + +## 组件与属性 + +| 组件 | 用途 | 属性 | +|------|------|------| +| `PhoneSearchBar` | 顶部搜索行:搜索框 + 扫码 + 圆形筛选按钮 | `hint`、`value`(双向)、`showScan`、`showFilter`、`upperCase`、`setOnScanClickListener`、`setOnFilterClickListener`、`setRefreshCallBack` | +| `PhoneStatusTab` | 状态 Tab 条(文字 + 角标 + 选中下划线) | `tabs`(List\)、`counts`(List\)、`value`(双向)、`setOnTabChanged` | +| `PhoneDataLayout` | 表单/筛选项,三形态 | `title`、`hint`、`type`(`PhoneDataLayoutType.INPUT`/`DATE`/`SPINNER`)、`value`(双向)、`list`、`required`、`enable`、`setRefreshCallBack` | +| `PhoneFilterPanel` | 底部筛选弹层(遮罩 + 面板 + 重置/确认) | `title`、`panelVisible`、`setOnResetClick`、`setOnConfirmClick`、`setOnDismissClick` | +| `PhoneBottomBar` | 底部操作条(全选 + 已选统计 + 主按钮) | `allChecked`、`countText`、`actionText`、`setOnAllCheckClick`、`setOnActionClick` | +| `PhoneStatBox` | 卡片内 2~4 列统计框,未传 label 的列自动隐藏 | `label1..4`、`value1..4` | +| `PhoneKvItem` | 详情页字段项(灰标签 + 数值) | `title`、`value`、`tag`(true → 橙色高亮标签) | + +`KeyValue` 是 `dev.utils.app.info.KeyValue`,字段是 **`key`(显示文案)+ `value`(业务值)**, +不是 `name`。`PhoneStatusTab` 的 `tabs` 就按 `KeyValue("待交接","0")` 传。 + +## PhoneFilterPanel 的内容插槽 + +筛选项直接写在标签内,组件 `onFinishInflate` 会自动把它们移进面板中部并施加 20dp 项间距, +使用方不用关心内部层级、也不用逐个写 `marginTop`: + +```xml + + + + + +``` + +记得在 `` 里 ``。 + +## ⚠️ 新增复合组件必做:屏蔽子控件状态恢复 + +同一页面放多个同类组件时(比如筛选弹层里 3 个 `PhoneDataLayout`),它们的内部子控件 +(`et`/`tv`/`spinner`…)**共用同一套 id**。系统按 id 保存/恢复视图状态会跨实例串档。 + +实际后果(出库交接踩过):DATE 项的默认日期被邻近输入框恢复的空文本覆盖, +`EditText.setText("")` 触发 `doOnTextChanged`,再经双向绑定把 ViewModel 的航班日期也写成空—— +**筛选条件静默丢失,界面上只表现为"日期没了",极难联想到状态恢复**。 + +所以每个含内部 id 的组件都要写: + +```kotlin +override fun dispatchSaveInstanceState(container: SparseArray) = + dispatchFreezeSelfOnly(container) + +override fun dispatchRestoreInstanceState(container: SparseArray) = + dispatchThawSelfOnly(container) +``` + +取值本来就由 ViewModel + DataBinding 持有,不需要视图级恢复,屏蔽掉没有副作用。 + +配套的第二道防线:多形态组件里,文本回写要限定形态,别让隐藏控件影响取值: + +```kotlin +et.doOnTextChanged { text, _, _, _ -> + if (type == PhoneDataLayoutType.INPUT) value = text.toString() +} +``` + +### 遇到"值被神秘清空"怎么定位 + +在 setter 里打一条带堆栈的日志,一次就能看到真凶: + +```kotlin +android.util.Log.d("DBG", "value '$field' -> '$v'", Throwable("trace")) +``` + +出库交接那次的栈是 `TextView.onRestoreInstanceState → EditText.setText → doOnTextChanged`, +指向非常明确。**排完记得删日志。** + +## 新增组件的写法约定 + +照现有 7 个组件的模式来,保持一致: + +1. 继承 `LinearLayout`/`FrameLayout`,`init` 里 `inflate(context, R.layout.layout_phone_xxx, this)` +2. 内部布局用 ``,避免多一层嵌套 +3. 属性做成 Kotlin `var` + setter 里立即生效;双向绑定值用 + `onChangeListener: InverseBindingListener?` +4. BindingAdapter 统一加到 `PhoneWidgetKtx.kt`,函数名带组件名前缀避免顶层函数重名 +5. 有互斥形态时,**`type` 要先于 `value` 生效**(把 type 放进同一个多属性 adapter 的第一个 + `?.let`),否则 value 会写进错误的子控件 +6. 加上上面那两个 `dispatch*SelfOnly` 覆写 +7. 完成后同步更新 `CLAUDE.md` 的组件表和记忆文件 `phone-5.5inch-adaptation.md` + +## 资源 + +配色一律用 `phone_*`,背景用 `bg_phone_*`,图标用 `ic_phone_*`,禁止写死色值。 +已有的(不够再加,加完更新 CLAUDE.md): + +- 色:`phone_primary` `phone_page_bg` `phone_bg` `phone_stat_bg` `phone_text_title/body/hint/label/strong/weak_btn` + `phone_divider` `phone_badge_bg` `phone_green` `phone_check_border` `phone_tag_gray_*` `phone_tag_green_*` + `phone_tag_red_*` `phone_orange_bg/text` +- 背景:`bg_phone_card` `bg_phone_search` `bg_phone_input` `bg_phone_stat_box` `bg_phone_panel_top` + `bg_phone_icon_round` `bg_phone_btn_primary` `bg_phone_btn_outline` `bg_phone_badge` + `bg_phone_tag_green/gray/red/orange` `bg_phone_card_header_blue/green` +- 图标:`ic_phone_airplane` `ic_phone_location` `ic_phone_person` `ic_phone_check_circle` + `ic_phone_chevron_right/down` `ic_phone_calendar` `ic_phone_close` + `ic_phone_check_round_checked/unchecked`(圆形复选框) +- 复用 Pad 的矢量图:`img_search` `img_scan` `img_filter`(可 `app:tint` 染色) + +设计稿里的 MDI 图标若缺失,直接写 24×24 的 vector(用 MDI 官方 path),比找位图靠谱且能染色。 diff --git a/.claude/skills/phone-adapt/references/pad-safety.md b/.claude/skills/phone-adapt/references/pad-safety.md new file mode 100644 index 0000000..9cc07d5 --- /dev/null +++ b/.claude/skills/phone-adapt/references/pad-safety.md @@ -0,0 +1,167 @@ +# Pad 端零破坏 & 易崩点 + +平板端是在跑的生产功能,适配手机不能改变它的任何行为。以下是必须遵守的约束和踩过的坑。 + +## 布局变体的三条硬约束 + +同名布局 + 资源限定符(`layout/` 手机 / `layout-sw600dp/` 平板)会让 DataBinding 生成 +**一个 Binding 基类 + 两个变体实现**,因此 Kotlin 侧零改动。代价是两个变体必须兼容: + +### 1. `` 必须完全一致 + +手机变体需要 `activity` 变量(暴露纯 UI 方法给 XML)时,**平板变体也要补上**,否则编译报 +`variable not found`。平板不用它,加个注释说明即可: + +```xml + + +``` + +### 2. 共用 id 双方都要保留 + +Activity / ViewHolder 引用到的 id(`srl`、`rv`、`iv_icon`、`checkIcon`…)两个变体都要有。 +可以换位置换样式,但 id 得在。 + +### 3. 单侧独有的 id 会变 `@Nullable` + +只在手机变体存在的 id(如「查看详情」的 `ll_detail`),Binding 基类里是可空字段, +Kotlin 侧必须判空: + +```kotlin +// 平板变体没有这个控件,为 null 时直接跳过 +binding.llDetail?.setOnClickListener { XxxDetailActivity.start(itemView.context, bean) } +``` + +编译器会强制你处理,不用担心漏掉。改完可以核对生成代码确认: + +```bash +grep -B3 "llDetail" module_gjc/build/generated/data_binding_base_class_source_out/debug/out/\ +com/lukouguoji/gjc/databinding/ItemXxxBinding.java +``` + +### ⛔ 绝对不要用「不同文件名 + 代码判断」切布局 + +`activity_xxx_phone.xml` 会生成 `ActivityXxxPhoneBinding`,而字段声明的类型是 +`ActivityXxxBinding`。泛型擦除让**编译期查不出来**,一进页面就 `ClassCastException`。 + +## 业务层零破坏的三个模式 + +### 新增查询维度:默认空值 + 仅非空进请求 + +平板布局没有对应控件 → 字段恒为空 → 不进请求体 → 平板查询与改造前逐字节一致。 + +```kotlin +val handoverState = MutableLiveData("") // 手机 Tab 绑这个,平板无控件 +val hoId = MutableLiveData("") + +val filterParams = mapOf( + "fdate" to flightDate.value?.ifEmpty { null }, + /* 原有字段… */ + "hoState" to handoverState.value?.ifEmpty { null }, // 空 → null → 不影响平板 + "hoId" to hoId.value?.ifEmpty { null }, +) +``` + +### 手机专属的额外请求:ViewModel 内部开关 + +Tab 角标计数、新增下拉字典这类请求,平板不需要,多发就是改变了平板行为(请求次数)。 +用一个内部布尔控制,由 Activity 在手机形态下开启: + +```kotlin +// ViewModel +private var phoneExtrasEnabled = false + +fun initPhoneExtras() { + phoneExtrasEnabled = true + handoverState.value = "0" // 手机默认停在第一个 Tab + DictUtils.getWHSUserList(addAll = false) { hoUserList.postValue(it) } +} + +override fun getData() { + /* 原有列表 + 统计请求… */ + if (phoneExtrasEnabled) loadTabCounts(filterParams) // 平板不触发 +} +``` + +```kotlin +// Activity +if (DeviceUtil.isPhone()) viewModel.initPhoneExtras() +``` + +`DeviceUtil.isPhone()` 只用来决定**数据默认值和额外请求**,**永远不用来选布局**。 + +### 纯 UI 状态放 Activity + +弹层显隐、Tab 高亮这类与业务无关的状态,用 `ObservableBoolean` 放在 Activity 上暴露给 XML, +不要污染 ViewModel: + +```kotlin +val filterPanelVisible = ObservableBoolean(false) +fun toggleFilterPanel() = filterPanelVisible.set(!filterPanelVisible.get()) +``` + +### 同名 id 在两个变体里必须是同一种控件 + +平板变体的 `btnMove` 是 `TextView`,手机版底部换成了 `PhoneBottomBar`——**不要为了复用 +Activity 里的 `binding.btnMove` 而把这个 id 安到 PhoneBottomBar 上**。同名不同类型会让 +DataBinding 把字段类型退化成公共父类,编译期未必报错,运行时行为难料。 + +正确做法:手机端的按钮点击走组件自身的 `setOnActionClick`,`btnMove` 就只留在平板变体里, +Activity 侧判空调用: + +```kotlin +binding.btnMove?.setOnClickListener { showMoveConfirmDialog() } +``` + +被 XML 调用的 Activity 方法记得改成 public。 + +### 调字典要对齐既有页面的参数口径 + +`DictUtils` 的方法参数常有"看起来合理但后端不认"的取值。出港移库的特码下拉一开始传 +`ieFlag="E"`(出港),接口返回空数组;而同模块既有页面(`GjcWeighingStartViewModel` 等) +一律传 `ieFlag=""`,能正常返回。 + +所以调字典前先 grep 一下同模块其他页面怎么调的,照抄它们的参数;改完必须在实机上 +**把下拉点开确认真的有数据**,空列表在 UI 上看不出报错。 + +### 共享方法别为手机改语义 + +`checkAllClick()` 这类平板也在用的方法,不要为了手机端的语义去改它。 +例:手机「待交接」Tab 下理论上只有未交接记录(服务端按状态过滤),所以全选照原样全量勾选就是对的; +若为此加上「跳过已交接」的过滤,反而改变了平板端(平板列表混排两种状态)的行为。 + +## 屏幕方向:Manifest 必须写资源引用 + +新增 Activity 注册时: + +```xml + +``` + +**不要写死 `userLandscape`。** `screenOrientation` 由系统在创建 Activity 窗口时生效, +那时业务代码还没跑;写死横屏后即使 `BaseActivity` 在 `super.onCreate` 之前改成竖屏, +用户也会看到「先横屏、约 1 秒后转竖屏」的闪屏和重建。 + +资源取值:`module_base/res/values/integers.xml` = 1(portrait), +`values-sw600dp/integers.xml` = 11(userLandscape)。全项目已统一替换。 + +## 改 module_base 公共代码时 + +`module_base` 被所有业务模块依赖,改动会影响全部页面。原则: + +- **只做增量**:加新组件、新颜色、新 drawable,别改既有组件的行为 +- 确实要改公共基类(`BaseActivity` / `BaseBindingActivity` / Pad 系组件)时, + **必须在平板上回归**至少 2~3 个不同类型的既有页面 +- Bean 上加只读计算属性是安全的(Gson 只序列化字段,不动 getter); + 加**字段**要谨慎,会进请求体 + +## 已知的既有问题(不是你改坏的) + +用 `am start` 直启页面时,若**先经过首页**再启目标页,会崩在 +`LoadingModel.showLoading` → XPopup `popupInfo is null`。在**未改动**的页面上同样复现, +属于既有缺陷。**冷启动直启不受影响**(`force-stop` 后直接 `am start`)。 + +遇到崩溃先做这个对照实验再下结论:拿一个你没碰过的页面用同样方式打开,看是否同样崩。 diff --git a/.claude/skills/phone-adapt/references/verification.md b/.claude/skills/phone-adapt/references/verification.md new file mode 100644 index 0000000..0499784 --- /dev/null +++ b/.claude/skills/phone-adapt/references/verification.md @@ -0,0 +1,166 @@ +# 端到端验证手册 + +目标:在**真实接口**下把手机端走通,并确认平板端没退化。只看编译通过是不够的—— +本次适配里"筛选条件被静默清空"和"后端不认新参数"两个问题,都只有跑真机才暴露。 + +## 环境 + +```bash +~/Library/Android/sdk/emulator/emulator -list-avds # Medium_Phone_API_36.1(手机) / Aerologic_Tablet(平板) +adb devices -l +adb -s shell wm size && adb -s shell wm density +``` + +判定形态:手机 1080×2400@420dpi → `PHONE(sw=411dp)`;平板 1280×800@160dpi → `TABLET(sw=800dp)`。 + +`ui_probe.sh` 封装了常用操作,比手写 adb 省事且更可靠: + +```bash +P=.claude/skills/phone-adapt/scripts/ui_probe.sh +$P form # 打印形态识别结果 +$P texts # 当前界面所有可见文字(做断言用) +$P bounds "已交接" # 元素 bounds + 中心点 +$P tap-text "确认" # 按文字点击(自动取中心点) +$P wait-text "待交接" # 等页面就绪 +$P wait-gone "请稍候……" # 等加载弹窗消失 +$P shot /tmp/a.png # 截图 +$P req pageQuery # 抓请求/响应体 +$P crash # 崩溃次数 + 栈 +``` + +## 构建安装 + +```bash +./gradlew assembleDebug 2>&1 | grep -E "^(BUILD|FAILURE)|error:" +adb -s install -r -d app/build/outputs/apk/debug/app-debug.apk +``` + +注意 gradle 输出里大量 `e: 注: ARouter::Compiler …` 是注解处理器的**提示**被误标成 `e:`, +不是错误;只看 `BUILD SUCCESSFUL` / `error:` 就行。 + +## 进入目标页面的两条路 + +### 正规路径(优先):登录 → 首页菜单 + +```bash +adb -s shell monkey -p com.lukouguoji.aerologic -c android.intent.category.LAUNCHER 1 +``` + +登录页账号密码需要用户提供。填表用 `input text`,注意 `#` 等字符要转义(`Aa123456\#`)。 +底部有「首页 / 国内 / 国际 / 我的」Tab,国际业务页找对应入口。 + +**首页菜单是按权限过滤的**:当前账号角色没有该权限时,入口根本不显示(本次 ADMIN 登录后 +国际业务只有「板箱过磅」「进港理货」,没有「出库交接」)。这时走下面的直启。 + +### 直启(权限缺失时的替代):冷启动 + am start + +`app/src/debug/AndroidManifest.xml` 里把调试页临时 `exported="true"`,就能直接拉起。 +**必须冷启动**(先 force-stop),否则会撞上既有的 LoadingModel 崩溃: + +```bash +adb -s shell am force-stop com.lukouguoji.aerologic +sleep 2 +adb -s shell am start -n com.lukouguoji.aerologic/<完整类名> +``` + +登录态存在 SharedPreference 里,冷启动直启同样带 token,接口能正常返回真实数据。 + +> 先经首页再 `am start` 会崩在 `LoadingModel.showLoading` → XPopup `popupInfo is null`, +> 这是既有缺陷(未改动的页面也复现),不是本次改动引入的。 + +## 点击前先等就绪 + +加载弹窗("请稍候……")会盖住整屏并**吞掉 `input tap`**,表现为"点了没反应"。 +本次验证就因此白跑了几轮。所以: + +```bash +$P wait-text "待交接" # 等目标元素出现 +$P tap-text "已交接" +$P texts | grep -c "全选" # 用文字变化确认点击确实生效 +``` + +点完**一定要断言效果**(用 `texts` 或截图),别假设点中了。 + +## 逐项走查清单 + +每一步做完都跑一次 `crash`(必须为 0): + +- [ ] 列表加载:卡片字段、各种状态形态(如待处理 / 已完成两种卡片) +- [ ] Tab 切换:指示条位置、角标数字、底部条按设计显隐 +- [ ] 筛选弹层:打开、各控件取值、重置、确认后重新查询 +- [ ] 下拉字典:真实取到数据(不是空列表) +- [ ] 多选:单选、全选联动、"已选 N 项"计数 +- [ ] 详情页/二级页:字段绑定、条件显示的区块 +- [ ] 扫码入口能拉起 + +## 核对请求参数是否真的生效 + +新增的查询字段要确认两件事:客户端**发出去了**,服务端**认**。 + +```bash +$P req pageQuery +``` + +OkHttp 日志是多行 pretty JSON。看到请求体里有你的字段(如 `"hoState": "0"`)只说明客户端对了。 +**服务端是否生效要用行为验证**:切到另一个 Tab,看返回数据是否真的变了。 + +本次实测:请求正确携带 `hoState:"0"/"1"`,但两个 Tab 返回同一批数据 → 后端没做过滤。 +这种情况**必须在交付说明里如实标注**,不能让它看起来是通的。 + +## 无数据时怎么核对 UI + +服务端当天可能没数据(列表空)。放宽条件(清空日期)再查;仍为空时,临时注入样例 Bean: + +```kotlin +// 临时:覆盖各种形态各一条,验证后删除 +binding.rv.postDelayed({ + binding.rv.commonAdapter()?.refresh(listOf(/* 待处理 / 危险品 / 已完成 各一条 */)) +}, 2500) +``` + +截图核对完**必须删除**,然后重新构建 + grep 确认无残留: + +```bash +grep -rn "injectMockForVisualCheck\|TODO 临时" module_base/src module_gjc/src | wc -l # 应为 0 +``` + +## 屏幕方向验证 + +新增/修改 Activity 后,确认手机端不会「先横屏再转竖屏」: + +```bash +# 冷启动时连续采样:应全程 mRotation=0 +adb -s shell am force-stop com.lukouguoji.aerologic; sleep 2 +adb -s shell monkey -p com.lukouguoji.aerologic -c android.intent.category.LAUNCHER 1 +for i in $(seq 1 10); do adb -s shell dumpsys window | grep -m1 -oE "mRotation=[0-9]+"; sleep 0.4; done +``` + +平板则应首屏就是横屏(截图宽 > 高)。若手机出现横屏帧,检查该 Activity 的 Manifest +是否漏写 `android:screenOrientation="@integer/screen_orientation"`。 + +## Pad 端回归(必做) + +```bash +adb -s install -r -d app/build/outputs/apk/debug/app-debug.apk +adb -s shell am start -n com.lukouguoji.aerologic/<同一个类名> +$P shot /tmp/tablet.png +$P form # 应为 TABLET(sw=800dp…) +``` + +对比改造前后:搜索条数量与顺序、日期默认值、按钮(平板可能比手机多按钮)、底部统计文案。 +改过 `module_base` 里的公共基类或 Pad 系组件时,这一步不能省,且要多看几个页面。 + +## 定位"值被神秘修改"类问题 + +在 setter 里打带堆栈的日志,一次就能看到调用来源: + +```kotlin +android.util.Log.d("DBG", "value '$field' -> '$v'", Throwable("trace")) +``` + +```bash +adb -s logcat -d -s DBG | grep -A14 "'旧值' -> ''" | grep "at com.lukouguoji\|at android" +``` + +本次靠这招定位到 `TextView.onRestoreInstanceState → EditText.setText → doOnTextChanged`, +即复合自定义 View 的 id 串档(见 `components.md`)。**排完删日志。** diff --git a/.claude/skills/phone-adapt/scripts/design_shots.py b/.claude/skills/phone-adapt/scripts/design_shots.py new file mode 100755 index 0000000..ed1c754 --- /dev/null +++ b/.claude/skills/phone-adapt/scripts/design_shots.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +""" +把 5.5 寸手持端设计稿(HTML 原型)渲染成截图,供逐像素比对。 + +设计稿是带 Tailwind + JS 的交互原型:列表页、Tab、详情页、筛选弹层往往挤在同一个 +HTML 里,靠 JS 函数切换。只读源码容易漏掉视觉细节(间距、圆角、真实配色、 +以及 JS 里 id 映射写错导致的字段错位),所以务必渲染成图来看。 + +用法: + # 1) 先列出 HTML 里可用的状态切换函数与元素 id,据此决定要截哪些状态 + python3 design_shots.py --html 出库交接.html --list + + # 2) 渲染:默认状态 + 注入 JS 触发的各个状态 + python3 design_shots.py --html 出库交接.html --out /tmp/shots \ + --state "01_列表:" \ + --state "02_已交接Tab:switchTab('shipped');" \ + --state "03_详情:showDetail({id:'PMC1',status:'已交接'});" \ + --state "04_筛选弹层:toggleFilterDrawer(true);" + +每个 --state 形如 "名称:JS",JS 可为空表示页面初始态。 +输出 /<名称>.png,同时保留注入后的 <名称>.html 便于复查。 +""" + +import argparse +import os +import re +import shutil +import subprocess +import sys +import urllib.parse + +CHROME_CANDIDATES = [ + "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", + "/Applications/Chromium.app/Contents/MacOS/Chromium", + shutil.which("google-chrome") or "", + shutil.which("chromium") or "", + shutil.which("chromium-browser") or "", +] + + +def find_chrome() -> str: + for path in CHROME_CANDIDATES: + if path and os.path.exists(path): + return path + sys.exit( + "找不到 Chrome/Chromium。请安装,或用 --chrome 指定可执行文件路径。" + ) + + +def list_hooks(html: str) -> None: + """列出可用于构造状态的 JS 函数和元素 id。""" + funcs = sorted(set(re.findall(r"function\s+([A-Za-z_$][\w$]*)\s*\(", html))) + onclicks = sorted(set(re.findall(r'onclick="([^"]+)"', html))) + ids = sorted(set(re.findall(r'id="([^"]+)"', html))) + + print("== JS 函数(可直接注入调用)==") + for f in funcs: + print(f" {f}()") + print("\n== onclick 表达式(含真实参数,照抄最省事)==") + for o in onclicks[:40]: + print(f" {o}") + if len(onclicks) > 40: + print(f" ... 其余 {len(onclicks) - 40} 条略") + print("\n== 元素 id(判断有哪些页面/弹层)==") + print(" " + ", ".join(ids)) + + +def render(chrome: str, html: str, name: str, js: str, out_dir: str, + width: int, height: int, scale: float, budget: int) -> str: + # 等 load 之后再触发,确保 CDN 的 Tailwind/Iconify 已生效 + inject = ( + "" + ) + page_path = os.path.join(out_dir, f"{name}.html") + with open(page_path, "w", encoding="utf-8") as fp: + fp.write(html.replace("", inject + "")) + + png_path = os.path.join(out_dir, f"{name}.png") + subprocess.run( + [ + chrome, + "--headless=new", + "--disable-gpu", + "--hide-scrollbars", + f"--force-device-scale-factor={scale}", + f"--window-size={width},{height}", + f"--virtual-time-budget={budget}", + f"--screenshot={png_path}", + "file://" + urllib.parse.quote(os.path.abspath(page_path)), + ], + capture_output=True, + ) + return png_path + + +def main() -> None: + ap = argparse.ArgumentParser() + ap.add_argument("--html", required=True, help="设计稿 HTML 路径") + ap.add_argument("--out", default="/tmp/design_shots", help="输出目录") + ap.add_argument("--state", action="append", default=[], + help='形如 "名称:JS",可重复;JS 为空表示初始态') + ap.add_argument("--list", action="store_true", + help="只列出可用的 JS 函数 / onclick / id,不截图") + ap.add_argument("--chrome", default="", help="Chrome 可执行文件路径") + # 原型容器一般是 375×812 的手机壳,留出边距后 460×900 刚好完整收进去 + ap.add_argument("--width", type=int, default=460) + ap.add_argument("--height", type=int, default=900) + ap.add_argument("--scale", type=float, default=2.0, help="缩放倍数,2 便于看清细节") + ap.add_argument("--budget", type=int, default=9000, + help="虚拟时间预算(ms),需覆盖 CDN 脚本加载") + args = ap.parse_args() + + with open(args.html, encoding="utf-8") as fp: + html = fp.read() + + if args.list: + list_hooks(html) + return + + chrome = args.chrome or find_chrome() + os.makedirs(args.out, exist_ok=True) + + states = args.state or ["01_default:"] + for spec in states: + name, _, js = spec.partition(":") + png = render(chrome, html, name.strip(), js, args.out, + args.width, args.height, args.scale, args.budget) + ok = os.path.exists(png) and os.path.getsize(png) > 0 + size = os.path.getsize(png) if ok else 0 + print(f"{'✓' if ok else '✗'} {name.strip():<24} {png} ({size} bytes)") + + print(f"\n用 Read 工具逐张查看 {args.out}/*.png,再开始写布局。") + + +if __name__ == "__main__": + main() diff --git a/.claude/skills/phone-adapt/scripts/ui_probe.sh b/.claude/skills/phone-adapt/scripts/ui_probe.sh new file mode 100755 index 0000000..5f75115 --- /dev/null +++ b/.claude/skills/phone-adapt/scripts/ui_probe.sh @@ -0,0 +1,119 @@ +#!/usr/bin/env bash +# 实机验证辅助:读取界面文字 / 按文字点击 / 截图 / 抓请求体。 +# +# 为什么需要它:手机端验证要反复点 Tab、弹层按钮、卡片链接。靠肉眼估坐标点击 +# 极易点空(本次适配就因此白跑了几轮),而 uiautomator 能拿到元素真实 bounds。 +# tap-text 直接按文字定位并点中心,比手算坐标可靠得多。 +# +# 用法: +# ui_probe.sh texts 列出当前界面所有可见文字 +# ui_probe.sh bounds "已交接" 打印该文字元素的 bounds 与中心点 +# ui_probe.sh tap-text "确认" [序号] 按文字点击(取中心点);同名多处时默认第 1 处 +# ui_probe.sh wait-text "待交接" [秒] 等文字出现(默认 20 秒),点击前先等页面就绪 +# ui_probe.sh wait-gone "请稍候……" [秒] 等文字消失(如等加载弹窗关闭) +# ui_probe.sh shot /tmp/a.png 截图到本地 +# ui_probe.sh req <关键字> 从 logcat 抓含关键字的请求/响应体 +# ui_probe.sh crash 统计并打印最近一次崩溃栈 +# ui_probe.sh form 打印形态识别结果 PHONE/TABLET + +set -uo pipefail + +SERIAL="${1:?用法: ui_probe.sh <命令> [参数]}" +CMD="${2:?缺少命令}" +ARG="${3:-}" +PKG="com.lukouguoji.aerologic" +A="adb -s $SERIAL" + +dump() { + $A shell uiautomator dump /sdcard/_probe.xml >/dev/null 2>&1 + # 注意:dump 出来的 XML 是一整行,必须按 '<' 拆成一节点一行才能按节点过滤。 + # (`tr '>' '>\n'` 是字符映射不是字符串替换,等于空操作,别踩这个坑。) + $A shell cat /sdcard/_probe.xml | tr '<' '\n' +} + +# 打印所有 text 完全等于 $1 的节点的 bounds 与中心点 +centers_of() { + dump | grep -F "text=\"$1\"" \ + | grep -oE 'bounds="\[[0-9]+,[0-9]+\]\[[0-9]+,[0-9]+\]"' \ + | sed -E 's/bounds="\[([0-9]+),([0-9]+)\]\[([0-9]+),([0-9]+)\]"/\1 \2 \3 \4/' \ + | awk '{printf "bounds=[%d,%d][%d,%d] center=%d,%d\n", $1,$2,$3,$4, ($1+$3)/2, ($2+$4)/2}' +} + +case "$CMD" in + texts) + dump | tr '<' '\n' | grep -oE 'text="[^"]+"' | sed 's/text=//;s/"//g' | awk '!seen[$0]++' + ;; + + bounds) + [ -z "$ARG" ] && { echo "需要文字参数"; exit 1; } + centers_of "$ARG" + ;; + + tap-text) + [ -z "$ARG" ] && { echo "需要文字参数"; exit 1; } + idx="${4:-1}" + all=$(centers_of "$ARG") + [ -z "$all" ] && { echo "界面上找不到文字:$ARG"; exit 1; } + total=$(echo "$all" | wc -l | tr -d ' ') + # 同一文字可能在多处出现(如底部 Tab「国际」与列表里的「国际」), + # 默认点第 1 个;命中多个时提示,必要时用第 4 个参数指定序号。 + if [ "$total" -gt 1 ]; then + echo "注意:${ARG} 命中 $total 处,正在点第 $idx 处(可用第 4 个参数指定序号)" + echo "$all" | nl -w2 -s' ' + fi + line=$(echo "$all" | sed -n "${idx}p") + [ -z "$line" ] && { echo "序号 $idx 超出范围(共 $total 处)"; exit 1; } + cx=${line#*center=}; cx=${cx%%,*} + cy=${line##*,} + # 变量必须写成 ${ARG}:紧跟中文标点时 $ARG 会被当成变量名的一部分 + echo "tap ${ARG} @ $cx,$cy" + $A shell input tap "$cx" "$cy" + ;; + + # 等某段文字出现 / 消失。点击前先等页面就绪很重要: + # 加载弹窗("请稍候……")会盖住整屏并吞掉 input tap,导致点击"静默失效"。 + wait-text) + [ -z "$ARG" ] && { echo "需要文字参数"; exit 1; } + for _ in $(seq 1 "${4:-20}"); do + if dump | grep -qF "text=\"$ARG\""; then echo "出现: ${ARG}"; exit 0; fi + sleep 1 + done + echo "超时未出现: ${ARG}"; exit 1 + ;; + + wait-gone) + [ -z "$ARG" ] && { echo "需要文字参数"; exit 1; } + for _ in $(seq 1 "${4:-20}"); do + if ! dump | grep -qF "text=\"$ARG\""; then echo "已消失: ${ARG}"; exit 0; fi + sleep 1 + done + echo "超时仍存在: ${ARG}"; exit 1 + ;; + + shot) + out="${ARG:-/tmp/shot.png}" + $A exec-out screencap -p > "$out" + echo "$out ($(wc -c < "$out") bytes)" + ;; + + req) + # OkHttp 日志是多行 pretty JSON,用 -v raw 拿干净文本再按关键字取上下文 + $A logcat -d -v raw | grep -B24 -A24 -- "${ARG:-POST}" | grep -E '^\s*"|POST|<-- [0-9]{3}' | tail -60 + ;; + + crash) + n=$($A logcat -d | grep -c "FATAL EXCEPTION" || true) + echo "FATAL EXCEPTION 次数: $n" + if [ "$n" -gt 0 ]; then + $A logcat -d | grep -A25 "FATAL EXCEPTION" | tail -30 + fi + ;; + + form) + $A logcat -d -s BaseActivity:D | grep -oE "(PHONE|TABLET)\(sw=[0-9]+dp[^)]*\)" | tail -3 + ;; + + *) + echo "未知命令: $CMD"; exit 1 + ;; +esac diff --git a/CHANGELOG.md b/CHANGELOG.md index c20f070..5fb81c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,101 +1,122 @@ -# 版本变更日志 (Changelog) - -本文档记录 AirLogistics 项目的所有重要变更。 - -格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/), -版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。 - -## [1.8.4] - 2024-12-02 - -### 新增 (Added) -- 完善 Claude Code 配置,添加 Android 开发权限 -- 创建 8 个快捷命令 (/build-debug, /install, /logs 等) -- 定制 CLAUDE.md 为 Android 项目专用开发指南 -- 添加 CONTRIBUTING.md 贡献指南文档 -- 添加 CHANGELOG.md 版本变更日志 - -### 改进 (Changed) -- 优化首页菜单交互体验 -- 改进 UI 界面显示效果 - -### 技术栈 -- Kotlin 1.6.21 -- Android Gradle Plugin 7.2.0 -- Gradle 7.3.3 -- minSdk 24, targetSdk 30, compileSdk 31 - ---- - -## [1.8.x] - 之前版本 - -### 主要功能 -- 国内出港业务模块 (货物收运、复磅称重、转运管理、出库装机) -- 国内进港业务模块 (舱单管理、卸机入库、出库提货、移库管理) -- 国际出港业务模块 (国际货物收运、板箱组装、ULD容器管理) -- 国际进港业务模块 (国际舱单管理、报文解析、理货管理) -- 航班管理模块 (航班查询、航班统计) -- 货物追踪模块 (货物状态追踪、运输日志) -- 监装监卸模块 (监装监卸管理) -- PDA功能模块 (PDA专用功能) -- 蓝牙打印模块 (佳博打印机集成) - -### 核心架构 -- MVVM 架构模式 -- 组件化模块设计 (11个业务模块 + 1个基础库) -- DataBinding 双向绑定 -- Kotlin Coroutines + Flow 异步处理 -- ARouter 模块间通信 -- Retrofit + OkHttp 网络请求 -- Glide 图片加载 -- MPAndroidChart 图表展示 - -### 开发基础设施 -- BaseActivity/BaseBindingActivity 基类 -- BaseViewModel/BasePageViewModel 基类 -- CommonAdapter + BaseViewHolder 列表适配 -- PadSearchLayout/PadDataLayout 自定义组件 -- 完整的 Kotlin 扩展函数库 -- DataBinding 适配器集合 - ---- - -## 版本说明 - -### 版本号规则 -- **Major.Minor.Patch** (例: 1.8.4) -- **Major**: 重大架构变更或不兼容的 API 修改 -- **Minor**: 新功能添加,向下兼容 -- **Patch**: Bug 修复和小的改进 - -### 变更类型 -- **Added**: 新增功能 -- **Changed**: 功能改进或变更 -- **Deprecated**: 即将废弃的功能 -- **Removed**: 已移除的功能 -- **Fixed**: Bug 修复 -- **Security**: 安全性修复 - ---- - -## 未来计划 - -### 待开发功能 -- [ ] 优化数据同步机制 -- [ ] 增强离线模式支持 -- [ ] 改进用户权限管理 -- [ ] 优化蓝牙打印稳定性 -- [ ] 添加数据导出功能 -- [ ] 性能监控和分析 - -### 技术改进 -- [ ] 升级到 Kotlin 2.0 -- [ ] 迁移到 Jetpack Compose -- [ ] 优化构建速度 -- [ ] 完善单元测试覆盖 -- [ ] 添加 UI 自动化测试 - ---- - -**维护**: 本文档应在每次版本发布时更新。 -**负责人**: 项目维护团队 -**最后更新**: 2024-12-02 +# 版本变更日志 (Changelog) + +本文档记录 AirLogistics 项目的所有重要变更。 + +格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/), +版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。 + +## [1.9.0] - 2026-07-29 + +### 新增 (Added) +- 5.5 寸手持端双形态适配框架:同名布局 + 资源限定符(`layout/` 手机、`layout-sw600dp/` 平板)自动切换,业务逻辑(ViewModel/ViewHolder)零改动 +- 新增 `DeviceUtil` 设备形态判定工具,及手机版公共组件库(`PhoneSearchBar`、`PhoneStatusTab`、`PhoneDataLayout`、`PhoneFilterPanel`、`PhoneBottomBar`、`PhoneStatBox`、`PhoneKvItem`) +- 完成「国际出港移库」「国际出港出库交接」两个页面的手机端适配,含各自的详情页(`IntExpMoveDetailActivity`、`IntExpOutHandoverDetailActivity`) +- 手机端首页菜单接入「出港移库」「出库交接」入口 + +### 修复 (Fixed) +- 修复手机端进入页面时「先横屏、约 1 秒后转竖屏」的闪屏问题:Manifest 统一改为 `android:screenOrientation="unspecified"`(全项目 192 处),由 `BaseActivity.applyDeviceOrientation()` 按设备形态在运行时锁定方向,避免系统建窗口时用错误方向 +- 修复平板端因中间方案(`@integer/screen_orientation` 资源限定符)引入的回归:先竖屏再转横屏,且交互后 UI 整体放大约 1.6 倍(AutoSize 误选平板竖屏基准所致);验证系统解析 Manifest 属性不套用设备限定符,恢复为 `unspecified` 方案后两端方向与缩放均恢复正常 +- AutoSize 增加手机竖屏专用设计基准 390×844dp,避免手机端沿用平板竖屏 720dp 基准导致 UI 压缩 + +### 技术栈 +- Kotlin 1.6.21 +- Android Gradle Plugin 7.2.0 +- Gradle 7.3.3 +- minSdk 24, targetSdk 30, compileSdk 31 + +--- + +## [1.8.4] - 2024-12-02 + +### 新增 (Added) +- 完善 Claude Code 配置,添加 Android 开发权限 +- 创建 8 个快捷命令 (/build-debug, /install, /logs 等) +- 定制 CLAUDE.md 为 Android 项目专用开发指南 +- 添加 CONTRIBUTING.md 贡献指南文档 +- 添加 CHANGELOG.md 版本变更日志 + +### 改进 (Changed) +- 优化首页菜单交互体验 +- 改进 UI 界面显示效果 + +### 技术栈 +- Kotlin 1.6.21 +- Android Gradle Plugin 7.2.0 +- Gradle 7.3.3 +- minSdk 24, targetSdk 30, compileSdk 31 + +--- + +## [1.8.x] - 之前版本 + +### 主要功能 +- 国内出港业务模块 (货物收运、复磅称重、转运管理、出库装机) +- 国内进港业务模块 (舱单管理、卸机入库、出库提货、移库管理) +- 国际出港业务模块 (国际货物收运、板箱组装、ULD容器管理) +- 国际进港业务模块 (国际舱单管理、报文解析、理货管理) +- 航班管理模块 (航班查询、航班统计) +- 货物追踪模块 (货物状态追踪、运输日志) +- 监装监卸模块 (监装监卸管理) +- PDA功能模块 (PDA专用功能) +- 蓝牙打印模块 (佳博打印机集成) + +### 核心架构 +- MVVM 架构模式 +- 组件化模块设计 (11个业务模块 + 1个基础库) +- DataBinding 双向绑定 +- Kotlin Coroutines + Flow 异步处理 +- ARouter 模块间通信 +- Retrofit + OkHttp 网络请求 +- Glide 图片加载 +- MPAndroidChart 图表展示 + +### 开发基础设施 +- BaseActivity/BaseBindingActivity 基类 +- BaseViewModel/BasePageViewModel 基类 +- CommonAdapter + BaseViewHolder 列表适配 +- PadSearchLayout/PadDataLayout 自定义组件 +- 完整的 Kotlin 扩展函数库 +- DataBinding 适配器集合 + +--- + +## 版本说明 + +### 版本号规则 +- **Major.Minor.Patch** (例: 1.8.4) +- **Major**: 重大架构变更或不兼容的 API 修改 +- **Minor**: 新功能添加,向下兼容 +- **Patch**: Bug 修复和小的改进 + +### 变更类型 +- **Added**: 新增功能 +- **Changed**: 功能改进或变更 +- **Deprecated**: 即将废弃的功能 +- **Removed**: 已移除的功能 +- **Fixed**: Bug 修复 +- **Security**: 安全性修复 + +--- + +## 未来计划 + +### 待开发功能 +- [ ] 优化数据同步机制 +- [ ] 增强离线模式支持 +- [ ] 改进用户权限管理 +- [ ] 优化蓝牙打印稳定性 +- [ ] 添加数据导出功能 +- [ ] 性能监控和分析 + +### 技术改进 +- [ ] 升级到 Kotlin 2.0 +- [ ] 迁移到 Jetpack Compose +- [ ] 优化构建速度 +- [ ] 完善单元测试覆盖 +- [ ] 添加 UI 自动化测试 + +--- + +**维护**: 本文档应在每次版本发布时更新。 +**负责人**: 项目维护团队 +**最后更新**: 2026-07-29 diff --git a/CLAUDE.md b/CLAUDE.md index fd8b34d..fe62cfb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -839,6 +839,281 @@ adb logcat | grep "com.lukouguoji.aerologic" # 日志 --- +## 5.5 寸手持端(手机版)双形态适配规范 + +项目需同时支持 **10 寸平板横屏** 与 **5.5 寸手机竖屏**。核心原则:**业务逻辑层完全复用,只重写布局**。 + +### 核心机制:布局按资源限定符自动切换 + +``` +res/layout-sw600dp/activity_xxx.xml ← 平板(最小宽度 >= 600dp) +res/layout/activity_xxx.xml ← 手机(兜底,5.5 寸约 360~411dp) +``` + +两个变体**同名**,DataBinding 会生成同一个 Binding 基类 + 两个变体实现: + +``` +ActivityXxxBinding.java 公共基类(Activity 中引用的就是它) +ActivityXxxBindingImpl.java 手机变体 +ActivityXxxBindingSw600dpImpl.java 平板变体 +``` + +因此 **Activity / ViewModel / ViewHolder 的 `layoutId()`、`itemLayoutId` 全部保持原样,无需任何设备判断**。 + +### ⛔ 严禁:用「不同文件名 + 代码判断」切换布局 + +```kotlin +// ❌ 错误:会生成两个不同的 Binding 类 +override fun layoutId() = + if (DeviceUtil.isPhone()) R.layout.activity_xxx_phone else R.layout.activity_xxx +``` + +`activity_xxx_phone.xml` 生成的是 `ActivityXxxPhoneBinding`,而 `binding` 字段声明的类型是 `ActivityXxxBinding`。 +泛型擦除导致**编译期不报错**,但一进入该页面就 `ClassCastException` 崩溃。**必须用同名文件 + 资源限定符。** + +### 布局变体的强制约束 + +| 约束 | 说明 | +|------|------| +| **DataBinding 变量必须完全一致** | 两个变体 `` 中的 `` 名称与类型必须相同,否则编译失败 | +| **共用控件 id 必须双方都有** | Activity / ViewHolder 中引用的 id(如 `srl`/`rv`/`checkIcon`/`iv_icon`)两个变体都要保留 | +| **单侧独有的 id 自动变 `@Nullable`** | 只在一个变体存在的 id,Binding 基类中会是可空字段,Kotlin 侧强制 null 检查(编译器自动保障,不用担心漏改) | + +### 已改造的基础设施 + +| 文件 | 作用 | +|------|------| +| `module_base/.../util/DeviceUtil.kt` | 设备形态判定。按 `smallestScreenWidthDp >= 600` 区分平板/手机;读 `Resources.getSystem()` 以绕开 AutoSize 对 density 的改写,保证判定稳定 | +| `module_base/BaseActivity.kt` | `applyDeviceOrientation()` 按形态锁方向(手机竖屏 / 平板横屏)。Manifest 统一写 `unspecified` 配合它使用。子类覆写 `lockOrientationByDevice()` 返回 false 可跳过 | +| `module_base/base/BaseBindingActivity.kt` | 注释固化变体约定(`layoutId()` 不做设备分支) | +| `module_base/MyApplication.kt` | **AutoSize 增加手机竖屏基准 390×844**(见下节) | +| `module_base/res/values/colors.xml` | 手机端配色 `phone_*` 系列 | +| `module_base/res/drawable/bg_phone_*.xml` | 手机端卡片、搜索框、状态标签、主按钮背景 | +| `module_base/res/layout/title_tool_bar.xml` | 手机版公共标题栏(平板版已移至 `layout-sw600dp/`) | + +`DeviceUtil` 用法: + +```kotlin +DeviceUtil.isPhone() // 是否手机 +DeviceUtil.isTablet() // 是否平板 +DeviceUtil.describe() // "PHONE(sw=411dp, force=AUTO)",日志排查用 +DeviceUtil.forceMode = DeviceUtil.ForceMode.PHONE // 调试:在平板上强制走手机布局 +``` + +> `DeviceUtil.layout(padId, phoneId)` 仅用于**极少数**确实需要代码级判断的场景(如非 DataBinding 的布局)。 +> **常规页面一律用资源限定符,不要调用它。** + +### ⚠️ 屏幕方向:Manifest 一律写 `unspecified`,由 `BaseActivity` 按形态锁定 + +**症状(改造前)**:手机上打开页面(开屏页最明显)先显示横屏,约 1 秒后才转竖屏,伴随 Activity 重建。 + +**原因**:`android:screenOrientation` 由系统在**创建 Activity 窗口时**生效,此时业务代码还没执行。 +Manifest 写死 `userLandscape` 时,即使 `BaseActivity` 在 `super.onCreate` 之前 +`setRequestedOrientation(PORTRAIT)`,也只能在横屏窗口已建好之后再纠正 → 必然闪一下。 + +**做法**:Manifest 统一写 `unspecified`,让系统按设备**当前物理方向**建窗口 +(平板横屏摆放 → 横屏起,手机 → 竖屏起,两端起始方向本就正确), +`BaseActivity.applyDeviceOrientation()` 再按形态锁定,不产生二次纠正: + +```xml + +``` + +全项目 192 处已统一(`module_p` 等 24 处本就是 `portrait` 的 PDA 页面保持不变)。 + +#### ⛔ 别用 `@integer/screen_orientation` 这类资源引用(已验证行不通) + +一度改成 `android:screenOrientation="@integer/screen_orientation"` + `values/`=portrait、 +`values-sw600dp/`=userLandscape,**看似优雅,实测是错的**: + +系统解析 Manifest 属性时**用的是默认配置,不套用设备限定符**,所以 `values-sw600dp/` 永远不会被选中, +所有 Activity 实际都拿到了 `values/` 的竖屏值。后果是平板端: + +1. 先竖屏、随后被 `BaseActivity` 纠正成横屏 —— 反而把闪屏问题搬到了平板上 +2. **AutoSize 在竖屏配置下选了平板竖屏基准 720dp**(density=1280/720≈1.78,正常应为 1280/1152≈1.11) + → 交互几次后整个 UI 放大约 1.6 倍 + +> 验证方法(可复现):把 `values/` 与 `values-sw600dp/` 的值**互换**,并临时让 +> `lockOrientationByDevice()` 返回 false(排除运行时纠正),装到平板上看首屏方向。 +> 结果是平板取了 `values/` 的值 → 证明限定符被忽略。 + +### ⚠️ AutoSize 设计基准必须区分手机(易漏且后果严重) + +项目使用 AndroidAutoSize,`MyApplication.initAutoSizeConfig()` 按方向+设备切换设计尺寸: + +| 场景 | 设计基准 | +|------|----------| +| 横屏(平板) | 1152 × 720 dp | +| 竖屏 + 手机 | **390 × 844 dp**(对应 5.5 寸设计稿画布) | +| 竖屏 + 平板 | 720 × 1280 dp | +| PictureSelector | 360 × 480 dp | + +**若手机沿用平板竖屏的 720dp 基准,手机上所有 dp 会被压缩约一半,布局全部错位。** + +### 手机版 UI 规范(依据 `documents/5.5寸手持端设计文件/` 设计稿) + +| 部位 | 规范 | +|------|------| +| 画布基准 | 390 × 844 dp | +| 顶栏 | 高 48dp,`@color/phone_primary`(#2563EB),左侧「‹ 返回」,标题居中 18sp 加粗 | +| 页面背景 | `@color/phone_bg` (#F3F4F6) | +| 列表卡片 | `@drawable/bg_phone_card`,圆角 12dp,`marginHorizontal=16dp`,`marginTop=12dp`,`padding=14dp` | +| 卡片头行 | 圆形勾选框 20dp(`radiobtn_checked_style`/`radiobtn_unchecked_style`)+ 运单号 15sp 加粗 + 右侧状态标签 | +| 卡片字段 | 两列网格,13sp,`@color/phone_text_body`,行距 8dp | +| 状态标签 | `bg_phone_tag_green`(已完成)/ `bg_phone_tag_gray`(未完成),11sp | +| 搜索行 | 搜索框 40dp 高 + `bg_phone_search`,内含放大镜 + 输入 + 扫码;右侧筛选按钮 40dp | +| 状态 Tab | 高 42dp,选中文字 `phone_primary` + 底部 28×3dp 指示条 | +| 底部操作条 | 白底 + `elevation=8dp`,全选 + 统计(13sp/11sp 两行)+ 主按钮 `bg_phone_btn_primary` | +| 筛选弹层 | `FrameLayout` 遮罩 `#80000000` + 底部白色面板,重置 / 确定各占一半 | + +### 手机版页面改造步骤 + +1. **移动平板布局**:`git mv res/layout/activity_xxx.xml res/layout-sw600dp/activity_xxx.xml`(item 布局同理) +2. **新建手机布局**:在 `res/layout/` 下创建**同名**文件,保持相同 `` 与共用控件 id +3. **Kotlin 侧不动**:`layoutId()`、`itemLayoutId`、ViewHolder 全部保持原样 +4. **纯 UI 交互**(Tab 切换、弹层显隐)写在 Activity,不污染 ViewModel;状态过滤优先复用 ViewModel 既有字段 +5. 手机布局顶部 `` 不变(变体自动切换) +6. **回到手机端首页加菜单入口**(最易遗忘,见下节)——不加的话页面在手机上根本进不去 + +### 手机端首页菜单入口(适配完必须加,否则没入口) + +手机端首页是 `module_p` 的 `PDAEnterActivity`(手持机首页),底部四个 Tab 对应: + +| Tab | ViewModel | 位置 | +|-----|-----------|------| +| 国内 | `GnViewModel` | `module_p/.../ui/enter/gn/` | +| 国际 | `GjViewModel` | `module_p/.../ui/enter/gj/` | + +**菜单项是手写清单,不是接口下发**。权限机制只做过滤:登录返回的权限串存在 +`SharedPreferenceUtil.getString(Constant.Share.authList)`(一个逗号分隔的长字符串), +菜单项按 `authList.contains(bean.key)` 决定显不显示。 + +所以「适配完页面但手机首页看不到入口」的原因通常**不是没权限,而是清单里没加**。 +排查顺序:先确认权限串里有对应 key,再去看清单。 + +```bash +# 看当前登录账号实际拥有的权限串 +adb -s shell "run-as com.lukouguoji.aerologic \ + cat /data/data/com.lukouguoji.aerologic/shared_prefs/data.xml" | tr ',' '\n' | grep -oE "App[A-Za-z]+" | sort -u +``` + +加一项就是加一行 —— `ActionBean` 的第 4 个参数填 ARouter 路由即可,无需写 when 分支 +(`module_p` 只依赖 `module_base`,看不到 `module_gjc` 等业务模块,跨模块只能走路由): + +```kotlin +ActionBean( + "出港移库", + R.drawable.gjc_yi_ku_icon, // 图标复用 Pad 端同款 + Constant.AuthName.GjcYiKuListActivity, // 权限串,与 Pad 端菜单保持一致 + ARouterConstants.ACTIVITY_URL_INT_EXP_MOVE // 有 route 就走通用跳转 +), +``` + +两点注意: + +- **权限串与路由都要和 Pad 端菜单对齐**:以 `app/.../HomeFragment.kt` 里该权限对应的 + `ARouter.build(...)` 为准。同一业务常有新旧两个 Activity(如移库的 `GjcYiKuListActivity` + 与 `IntExpMoveActivity`),Pad 菜单实际跳的才是要适配的那个 +- **图标**:`module_p` 看不到 `module_gjc` 的资源,把 Pad 图标 PNG 复制一份到 + `module_p/src/main/res/drawable-xxhdpi/`(该模块既有 4 个图标就是这么放的,同名不同密度桶可共存) + +**示例:状态 Tab 零 ViewModel 改动**(`IntExpMoveActivity` 已实现) + +```kotlin +// Activity 中新增纯 UI 方法,写入 ViewModel 既有的 moveState 字段("" 全部 / "0" 未移库 / "1" 已移库) +fun switchTab(state: String) { + if (viewModel.moveState.value == state) return + viewModel.moveState.value = state + viewModel.searchClick() // 复用原有查询链路 +} +``` + +```xml + +android:textColor="@{`0`.equals(viewModel.moveState) ? @color/phone_primary : @color/phone_text_body}" +``` + +### 手机版公共组件库(`module_base/.../ui/weight/phone/`) + +7 个组件覆盖设计稿中反复出现的部件,**新页面优先复用,不要重写 XML**。属性均为无命名空间写法, +DataBinding 适配器统一放在 `PhoneWidgetKtx.kt`(同名属性按控件类型解析,与平板端 Pad* 组件互不冲突)。 + +| 组件 | 用途 | 关键属性 | +|------|------|----------| +| `PhoneSearchBar` | 顶部搜索行:搜索框 + 扫码 + 圆形筛选按钮 | `hint`、`value`(双向)、`showScan`、`showFilter`、`upperCase`、`setOnScanClickListener`、`setOnFilterClickListener`、`setRefreshCallBack` | +| `PhoneStatusTab` | 状态 Tab 条(文字 + 角标,选中态下划线) | `tabs`(List\)、`counts`(List\)、`value`(双向)、`setOnTabChanged` | +| `PhoneDataLayout` | 表单/筛选项,`PhoneDataLayoutType` = `INPUT`/`DATE`/`SPINNER` | `title`、`hint`、`type`、`value`(双向)、`list`、`required`、`enable`、`setRefreshCallBack` | +| `PhoneFilterPanel` | 底部筛选弹层(遮罩 + 面板 + 重置/确认) | `title`、`panelVisible`、`setOnResetClick`、`setOnConfirmClick`、`setOnDismissClick` | +| `PhoneBottomBar` | 底部操作条:全选 + 已选统计 + 主按钮 | `allChecked`、`countText`、`actionText`、`setOnAllCheckClick`、`setOnActionClick` | +| `PhoneStatBox` | 卡片内 2~4 列统计框(未传 label 的列自动隐藏) | `label1..4`、`value1..4` | +| `PhoneKvItem` | 详情页字段项(灰标签 + 数值),`tag=true` 转橙色高亮 | `title`、`value`、`tag` | + +**`PhoneFilterPanel` 自带内容插槽**:把 `PhoneDataLayout` 直接写在其标签内即可,组件会自动移入面板中部 +并施加 20dp 项间距,无需关心内部层级: + +```xml + + + + + +``` + +#### ⚠️ 复合自定义 View 必须屏蔽子控件状态恢复(已踩坑) + +同一页面放多个 `PhoneDataLayout`/`PhoneStatBox` 时,它们的内部子控件(`et`/`tv`/`spinner`…)**共用同一套 id**。 +系统按 id 保存/恢复视图状态会跨实例串档 —— 实测表现为:DATE 项的默认日期被邻近输入框恢复的空文本清空, +并通过双向绑定把 ViewModel 字段也写成了空值(筛选条件静默丢失)。 + +因此每个含内部 id 的手机版组件都重写了: + +```kotlin +override fun dispatchSaveInstanceState(container: SparseArray) = dispatchFreezeSelfOnly(container) +override fun dispatchRestoreInstanceState(container: SparseArray) = dispatchThawSelfOnly(container) +``` + +**新增同类组件时必须照做**(取值由 ViewModel + DataBinding 持有,本就不需要视图级恢复)。 + +### 已完成 / 待办 + +- ✅ **已完成**:适配框架 + 手机端公共资源 + 7 个手机版公共组件 +- ✅ **已完成页面**: + - 「国际出港移库」`IntExpMoveActivity`(框架参考页,筛选弹层内暂仍用 `PadSearchLayout`) + - 「国际出港出库交接」`IntExpOutHandoverActivity` + 「板箱详情」`IntExpOutHandoverDetailActivity` + (公共组件首个完整落地页,双端实机验证通过) +- ⏳ **待办**: + - 把「移库」页筛选弹层内的 `PadSearchLayout` 换成 `PhoneDataLayout`,视觉统一 + - `PhoneSearchBar` 接入 AutoQuery 联想(`AutoQueryManager` 目前只对接了 Pad 系组件) + +### 调试便利:直接拉起页面 + +`app/src/debug/AndroidManifest.xml`(**仅 Debug 生效,不进 Release 包**)通过 `tools:replace` 将适配调试页临时置为 `exported="true"`,免去每次登录再逐级点入: + +```bash +adb shell am start -n com.lukouguoji.aerologic/com.lukouguoji.gjc.page.move.IntExpMoveActivity +adb shell am start -n com.lukouguoji.aerologic/com.lukouguoji.gjc.activity.IntExpOutHandoverActivity +``` + +新增调试页时在该文件追加对应 `` 即可。 + +> 模拟器通常连不上内网服务(提示「接口访问失败」),列表为空。若需验证卡片/详情的还原度, +> 可在 Activity 里临时注入几条样例 Bean(`binding.rv.commonAdapter()?.refresh(list)`)截图比对,**验证后务必删除**。 + +**参考文件**:`module_base/.../util/DeviceUtil.kt`、`module_gjc/res/layout/activity_int_exp_move.xml`(手机)、`module_gjc/res/layout-sw600dp/activity_int_exp_move.xml`(平板) + +--- + ## Import 路径速查 ### 基类与常用类 @@ -870,6 +1145,7 @@ adb logcat | grep "com.lukouguoji.aerologic" # 日志 | 类 | 正确路径 | |----|----------| | `DictUtils` | `com.lukouguoji.module_base.util.DictUtils` | +| `DeviceUtil` | `com.lukouguoji.module_base.util.DeviceUtil` | | `MediaUtil` | `com.lukouguoji.module_base.util.MediaUtil` | | `UploadUtil` | `com.lukouguoji.module_base.util.UploadUtil` | | `KeyValue` | `dev.utils.app.info.KeyValue` | @@ -896,6 +1172,12 @@ adb logcat | grep "com.lukouguoji.aerologic" # 日志 | 资源引用不存在 | drawable/color/string 缺失 | 先检查资源是否存在,不存在则创建或用已有资源 | | `View.VISIBLE` 报错 | 未导入 | XML `` 中加 `` | | `textStyle` DataBinding 报错 | 不支持 | 用固定值 `android:textStyle="bold"` | +| 手机版页面一进入就 `ClassCastException` | 用了「不同文件名 + 代码判断」切换布局,生成了两个 Binding 类 | 改用同名布局 + 资源限定符(`layout/` 与 `layout-sw600dp/`),见「5.5 寸手持端双形态适配规范」 | +| 布局变体编译报 `variable not found` | 两个变体的 `` 中 `` 不一致 | 手机与平板变体的变量名/类型必须完全相同 | +| 手机上元素小一半 / 布局错位 | AutoSize 仍按平板 720dp 基准换算 | 确认 `MyApplication.initAutoSizeConfig()` 中手机竖屏走 390×844 分支 | +| 手机版筛选项默认值(如日期)自动被清空 | 多个复合自定义 View 内部子控件 id 相同,系统按 id 恢复状态时跨实例串档 | 组件重写 `dispatchSaveInstanceState`/`dispatchRestoreInstanceState` 为 `dispatchFreezeSelfOnly`/`dispatchThawSelfOnly`(见「手机版公共组件库」) | +| 手机上页面先横屏再转竖屏(闪一下) | Manifest 写死 `screenOrientation="userLandscape"`,系统建窗口时已按横屏,代码纠正为时已晚 | 改成 `android:screenOrientation="unspecified"`,由 `BaseActivity` 按形态锁定(见「屏幕方向」小节) | +| 平板先竖屏再转横屏 + 交互后 UI 放大约 1.6 倍 | Manifest 用了 `@integer/screen_orientation` 资源引用;系统解析 Manifest 不套用限定符,全部取到竖屏值,AutoSize 随之选了平板竖屏 720dp 基准 | Manifest 改回 `unspecified`(见「屏幕方向」小节的 ⛔ 说明) | --- @@ -961,10 +1243,16 @@ private fun loadDictLists() { ```xml + android:exported="false" + android:screenOrientation="unspecified" /> ``` +> `screenOrientation` **必须写 `unspecified`**,不要写死 `userLandscape`、也不要用资源引用。 +> 写死横屏会让手机端「先横屏、约 1 秒后转竖屏」闪一下;资源引用则会让平板端出问题 +> (详见下方「屏幕方向」小节)。 + 3. 在 `ARouterConstants` 注册路由(如需) 4. 标题栏统一用 ``,Activity 中 `setBackArrow("标题")` +5. **双形态布局**:需同时支持手机的页面,平板布局放 `res/layout-sw600dp/`、手机布局放 `res/layout/`,两者**同名**且变量与共用 id 一致。详见「5.5 寸手持端双形态适配规范」 ### 常见业务操作 @@ -1112,6 +1400,9 @@ Glide.with(itemView.context).load(glideUrl).into(binding.ivThumbnail) - `ic_new_expand`(全部展开/收起)36dp + padding 4dp - **图标之间间距统一 `marginStart=16dp`**(禁止使用 8dp,会导致视觉过近) - 常用资源: `bg_white_radius_8`、`colorPrimary`、`text_normal`、`text_gray`、`color_bottom_layout` +- **双形态适配:逻辑与 UI 严格分离** — 手机版只重写布局,业务逻辑一律复用现有 ViewModel / ViewHolder;纯 UI 交互(Tab 切换、弹层显隐)写在 Activity,不下沉到 ViewModel +- **禁止用不同文件名切换布局** — 手机/平板布局必须同名 + 资源限定符,否则 `ClassCastException`(详见「5.5 寸手持端双形态适配规范」) +- 手机版资源统一使用 `phone_*` 颜色与 `bg_phone_*` drawable,禁止直接写死色值 ### 环境配置 @@ -1125,4 +1416,16 @@ Glide.with(itemView.context).load(glideUrl).into(binding.ivThumbnail) 2. 资源引用错误 → 检查 drawable/color/string 是否存在 3. DataBinding 错误 → 检查 import、枚举值、View 类导入 4. suspend function 错误 → 在 `viewModelScope.launch` 中调用 -5. 仍有问题 → `./gradlew clean` 后重新构建 +5. 双形态布局问题 → 查「常见编译错误速查」中 3 条布局变体相关条目;可用 `DeviceUtil.describe()` 打日志确认当前形态 +6. 仍有问题 → `./gradlew clean` 后重新构建 + +### 双端验证命令 + +```bash +~/Library/Android/sdk/emulator/emulator -list-avds # 可用:Medium_Phone_API_36.1(手机)、Aerologic_Tablet(平板) +adb -s <设备> shell wm size && adb -s <设备> shell wm density # 确认屏幕参数 +adb -s <设备> logcat -d -s BaseActivity:D # 查看形态识别结果 PHONE(sw=411dp) / TABLET(sw=800dp) +adb -s <设备> exec-out screencap -p > /tmp/shot.png # 截图比对 +``` + +> 改动 `BaseActivity` / `BaseBindingActivity` / 公共组件后,**必须在平板上回归**,确认现有平板版行为不变。 diff --git a/README.md b/README.md index 462aa44..6e21cb0 100644 --- a/README.md +++ b/README.md @@ -1,301 +1,326 @@ -# AirLogistics - 航空物流信息管理系统 - -一款专业的航空物流管理Android应用,为机场货运站提供全流程数字化解决方案,涵盖国内外货物进出港、仓储管理、车辆调度等核心业务。 - -## 📋 项目信息 - -- **版本**: 1.7.9 (versionCode 79) -- **包名**: com.lukouguoji.aerologic -- **最低支持**: Android 7.0 (API 24) -- **目标版本**: Android 10 (API 30) -- **开发语言**: Kotlin + Java -- **架构模式**: MVVM + 组件化 - -## 🏗️ 架构设计 - -### 核心架构 - -``` -┌─────────────────────────────────────────────────────┐ -│ 应用层 (App) │ -├─────────────────────────────────────────────────────┤ -│ 国内出港 │ 国内进港 │ 国际出港 │ 国际进港 │ -│ (GNC) │ (GNJ) │ (GJC) │ (GJJ) │ -├─────────────────────────────────────────────────────┤ -│ 基础服务层 (module_base) │ -│ • MVVM基类 • 网络框架 • UI组件 • 工具类 │ -├─────────────────────────────────────────────────────┤ -│ 蓝牙打印 │ 图表库 │ 航班管理 │ 货物追踪 │ -│ (Printer) │ (Chart) │ (Hangban) │ (Cargo) │ -└─────────────────────────────────────────────────────┘ -``` - -### MVVM模式 - -- **View层**: Activity/Fragment + DataBinding -- **ViewModel层**: BaseViewModel / BasePageViewModel -- **Model层**: Repository + Retrofit API -- **数据流**: 协程(Coroutines) + Flow - -### 组件化架构 - -- **模块独立**: 通过`isBuildModule`参数控制模块独立运行或集成 -- **路由通信**: ARouter实现模块间页面跳转和通信 -- **事件总线**: FlowBus(基于Flow) + EventBus -- **依赖注入**: 基于ServiceLoader的服务发现机制 - -### 基础设施 - -#### 核心基类 -- `BaseActivity`: 协程支持、Loading管理、扫码功能、键盘控制 -- `BaseBindingActivity`: DataBinding自动绑定、ViewModel生命周期管理 -- `BaseViewModel`: Loading管理、Activity结果处理 -- `BasePageViewModel`: 分页列表专用,集成PageModel自动处理分页 -- `CommonAdapter + BaseViewHolder`: 统一列表适配器封装 - -#### 网络请求层 -- **ServiceCreator**: Retrofit实例创建,动态IP配置 -- **拦截器**: 自动添加Token、时间戳,统一错误处理 -- **扩展函数**: - - `launchCollect`: 无Loading的后台请求 - - `launchLoadingCollect`: 带Loading的关键操作 - - `toRequestBody`: Map/Bean自动转JSON - -#### 统一UI组件 -- **PadSearchLayout**: 搜索输入框组合控件(支持文本/数字/下拉/日期) -- **PadDataLayout**: 数据展示/编辑组合控件(标题对齐) -- **StatusView**: 状态栏占位View -- **统一样式**: 颜色、字体、圆角、间距的全局规范 - -## 🚀 技术栈 - -### 核心框架 -- **Kotlin**: 1.6.21 + Coroutines 1.6.0 -- **Jetpack**: ViewModel、LiveData、DataBinding -- **网络**: Retrofit 2.6.1 + OkHttp 3.12.12 -- **JSON**: FastJSON 1.2.73 + Gson 2.10.1 - -### UI相关 -- **Material Design**: Material Components -- **屏幕适配**: AutoSize 1.2.+ (横屏1152dp × 720dp) -- **下拉刷新**: SmartRefreshLayout 2.0.3 -- **图表**: MPAndroidChart (定制版) -- **弹窗**: XPopup 2.9.19 -- **图片**: Glide 4.15.1 + PictureSelector v3.11.2 - -### 功能组件 -- **路由**: ARouter 1.5.2 -- **扫码**: ZXing 2.2.9 -- **权限**: AndPermission 2.0.2 -- **打印**: 佳博SDK 2.0.4 -- **日志**: Timber 5.0.1 - -## 💼 核心业务模块 - -### 国内出港 (module_gnc) -货物收运、复磅称重、转运管理、出库装机、仓库管理、数据统计 - -### 国内进港 (module_gnj) -舱单管理、卸机入库、出库提货、移库管理、货物交接、实时查询 - -### 国际出港 (module_gjc) -国际货物收运、板箱组装、ULD容器管理、复磅称重、仓储移库 - -### 国际进港 (module_gjj) -国际舱单管理、报文解析、理货管理、出库操作、货物交接 - -### 支持模块 -- **航班管理** (module_hangban): 航班查询、航班统计 -- **货物追踪** (module_cargo): 货物状态追踪、运输日志 -- **监装监卸** (module_mit): 监装监卸管理 -- **PDA功能** (module_p): PDA专用功能 -- **蓝牙打印** (Printer): 佳博打印机SDK集成 - -## 📦 项目结构 - -``` -aerologic-app/ -├── app/ # 应用壳层,整合所有业务模块 -├── module_base/ # 核心基础库,提供所有通用能力 -│ ├── base/ # MVVM基类 -│ ├── http/ # 网络请求框架 -│ ├── ui/weight/ # 统一UI组件 -│ ├── ktx/ # Kotlin扩展函数 -│ ├── bean/ # 数据模型 -│ └── router/ # ARouter路由常量 -├── module_gnc/ # 国内出港业务 -├── module_gnj/ # 国内进港业务 -├── module_gjc/ # 国际出港业务 -├── module_gjj/ # 国际进港业务 -├── module_hangban/ # 航班查询管理 -├── module_cargo/ # 货物追踪查询 -├── module_mit/ # 监装监卸管理 -├── module_p/ # PDA专用功能 -├── Printer/ # 蓝牙打印模块 -├── MPChartLib/ # 定制图表库 -├── CLAUDE.md # 详细开发指南 -└── README.md # 项目说明文档 -``` - -## 🚀 快速开始 - -### 环境要求 - -- **IDE**: Android Studio Arctic Fox (2020.3.1) 或更高版本 -- **JDK**: 1.8 -- **Gradle**: 7.3.3 -- **Kotlin**: 1.6.21 - -### 依赖配置 - -如遇依赖下载问题: - -1. 下载 gradle-7.3.3-bin.zip - - 百度网盘: https://pan.baidu.com/s/18wsuGRlNxjMYbxLhBH9yeg - - 提取码: 1029 - -2. 配置Gradle: - - Settings → Build, Execution, Deployment → Build Tools → Gradle - - 解压并替换到 "Gradle user home" 目录 - -### 构建项目 - -```bash -# 克隆项目 -git clone [repository-url] -cd aerologic-app - -# 清理构建 -./gradlew clean - -# 构建Debug版本 -./gradlew assembleDebug - -# 构建Release版本(已签名) -./gradlew assembleRelease - -# 安装到设备 -./gradlew installDebug -``` - -### 组件化开发模式 - -支持模块独立运行调试: - -1. 编辑 `gradle.properties` -2. 设置 `isBuildModule=true` (独立模块) 或 `false` (集成模式) -3. Sync项目并运行对应模块 - -## ⚙️ 配置说明 - -### 网络配置 - -服务器地址配置位置: -- **文件**: `module_base/src/main/res/values/strings.xml` -- **主服务器**: `system_url_inner` -- **地磅服务器**: `weight_url` -- **运行时**: 可通过SharedPreferences动态修改IP地址 - -### 签名配置 - -Release版本签名信息: -- **KeyStore**: `key.jks` (项目根目录) -- **密码**: storePassword/keyPassword均为 `123321` -- **别名**: `key` - -### 网络安全 - -- **超时时间**: 30秒(连接/读取/写入) -- **认证方式**: Bearer Token(自动添加) -- **HTTP支持**: 配置在 `res/xml/network_security_config.xml` - -## 📚 开发文档 - -详细的开发指南请参考 **[CLAUDE.md](./CLAUDE.md)**,包含: - -- ✅ 完整的架构详解(基类、网络、UI组件) -- ✅ 标准开发模板(Activity、ViewModel、ViewHolder) -- ✅ 实际业务示例(列表页、详情页、编辑页) -- ✅ 开发检查清单(7步列表页、4步详情页、5步编辑页) -- ✅ DataBinding适配器(10+种) -- ✅ Kotlin扩展函数(20+种) -- ✅ 常见业务场景实现 - -## 🔄 Git工作流 - -### 分支策略 - -- **develop**: 主开发分支 -- **feature/xxx**: 功能开发分支 -- **release/x.x.x**: 发布分支 -- **hotfix/xxx**: 紧急修复分支 - -### 当前分支 - -- **开发分支**: feature/hefei -- **主分支**: develop(用于PR) - -### 提交规范 - -提交前确保: -- ✅ 代码编译通过 -- ✅ 无明显错误和警告 -- ✅ 遵循项目代码规范 - -## 📋 开发原则 - -1. ✅ **优先使用现有基类和封装**,避免重复造轮子 -2. ✅ **充分利用PadDataLayout和PadSearchLayout组件**,保证UI一致性 -3. ✅ **遵循统一的命名和目录组织规范** -4. ✅ **使用DataBinding简化代码**,减少findViewById -5. ✅ **利用扩展函数处理通用逻辑**(Toast、Dialog、权限等) -6. ✅ **保持架构一致性**,新增业务参考现有模块 - -## 🔐 特性亮点 - -### 1. 高度组件化 -- 业务模块完全解耦,支持独立开发、测试、发布 -- 通过ARouter实现模块间通信,无需直接依赖 - -### 2. 统一UI规范 -- 自定义PadSearchLayout、PadDataLayout组合控件 -- 全局统一的颜色、字体、圆角、间距规范 -- 丰富的DataBinding适配器,简化UI开发 - -### 3. 高效网络框架 -- 协程+Flow的现代化异步方案 -- 统一的请求封装(launchCollect/launchLoadingCollect) -- 自动的Loading管理和错误处理 - -### 4. 完善的基础设施 -- BaseActivity提供扫码、Loading、键盘控制等通用能力 -- BasePageViewModel自动处理分页逻辑 -- CommonAdapter统一列表适配器管理 - -### 5. 丰富的工具扩展 -- 20+ Kotlin扩展函数(Toast、Dialog、JSON、日期等) -- 10+ DataBinding适配器(图片加载、可见性、Shape等) -- 完整的业务开发模板和检查清单 - -## 🛠️ 技术特点 - -- **响应式编程**: Kotlin Coroutines + Flow -- **声明式UI**: DataBinding双向绑定 -- **函数式编程**: Kotlin扩展函数和高阶函数 -- **依赖注入**: 基于ServiceLoader的轻量级方案 -- **模块化路由**: ARouter组件化通信 -- **横屏适配**: AutoSize自动适配1152dp × 720dp -- **蓝牙打印**: 佳博打印机SDK深度集成 -- **二维码扫描**: ZXing高性能扫码 - -## 📄 许可证 - -本项目为企业内部系统,版权归所属公司所有。 - -## ⚠️ 注意事项 - -**重要**: 本项目包含敏感业务信息和配置,仅供授权人员使用,严禁外传。 - ---- - -**文档维护**: 本README提供项目概览和架构信息,详细开发指南请参考 [CLAUDE.md](./CLAUDE.md) +# AirLogistics - 航空物流信息管理系统 + +一款专业的航空物流管理Android应用,为机场货运站提供全流程数字化解决方案,涵盖国内外货物进出港、仓储管理、车辆调度等核心业务。 + +## 📋 项目信息 + +- **版本**: 1.7.9 (versionCode 79) +- **包名**: com.lukouguoji.aerologic +- **最低支持**: Android 7.0 (API 24) +- **目标版本**: Android 10 (API 30) +- **开发语言**: Kotlin + Java +- **架构模式**: MVVM + 组件化 + +## 🏗️ 架构设计 + +### 核心架构 + +``` +┌─────────────────────────────────────────────────────┐ +│ 应用层 (App) │ +├─────────────────────────────────────────────────────┤ +│ 国内出港 │ 国内进港 │ 国际出港 │ 国际进港 │ +│ (GNC) │ (GNJ) │ (GJC) │ (GJJ) │ +├─────────────────────────────────────────────────────┤ +│ 基础服务层 (module_base) │ +│ • MVVM基类 • 网络框架 • UI组件 • 工具类 │ +├─────────────────────────────────────────────────────┤ +│ 蓝牙打印 │ 图表库 │ 航班管理 │ 货物追踪 │ +│ (Printer) │ (Chart) │ (Hangban) │ (Cargo) │ +└─────────────────────────────────────────────────────┘ +``` + +### MVVM模式 + +- **View层**: Activity/Fragment + DataBinding +- **ViewModel层**: BaseViewModel / BasePageViewModel +- **Model层**: Repository + Retrofit API +- **数据流**: 协程(Coroutines) + Flow + +### 组件化架构 + +- **模块独立**: 通过`isBuildModule`参数控制模块独立运行或集成 +- **路由通信**: ARouter实现模块间页面跳转和通信 +- **事件总线**: FlowBus(基于Flow) + EventBus +- **依赖注入**: 基于ServiceLoader的服务发现机制 + +### 基础设施 + +#### 核心基类 +- `BaseActivity`: 协程支持、Loading管理、扫码功能、键盘控制 +- `BaseBindingActivity`: DataBinding自动绑定、ViewModel生命周期管理 +- `BaseViewModel`: Loading管理、Activity结果处理 +- `BasePageViewModel`: 分页列表专用,集成PageModel自动处理分页 +- `CommonAdapter + BaseViewHolder`: 统一列表适配器封装 + +#### 网络请求层 +- **ServiceCreator**: Retrofit实例创建,动态IP配置 +- **拦截器**: 自动添加Token、时间戳,统一错误处理 +- **扩展函数**: + - `launchCollect`: 无Loading的后台请求 + - `launchLoadingCollect`: 带Loading的关键操作 + - `toRequestBody`: Map/Bean自动转JSON + +#### 统一UI组件 +- **PadSearchLayout**: 搜索输入框组合控件(支持文本/数字/下拉/日期) +- **PadDataLayout**: 数据展示/编辑组合控件(标题对齐) +- **StatusView**: 状态栏占位View +- **统一样式**: 颜色、字体、圆角、间距的全局规范 + +#### 双形态适配(平板 / 手机) +同时支持 **10 寸平板横屏** 与 **5.5 寸手机竖屏**,业务逻辑层完全复用,只重写布局。 + +- **DeviceUtil**: 设备形态判定(按 `smallestScreenWidthDp >= 600` 区分),提供调试用强制形态开关 +- **布局自动切换**: 通过 Android 资源限定符实现,`res/layout-sw600dp/`(平板)与 `res/layout/`(手机)下放**同名**布局,DataBinding 生成同一个 Binding 类,Activity / ViewModel / ViewHolder 无需任何设备判断 +- **屏幕方向**: Manifest 统一写 `android:screenOrientation="unspecified"`,系统按设备当前物理方向建窗口,`BaseActivity.applyDeviceOrientation()` 再按形态锁定(手机竖屏 / 平板横屏),两端均无「先横屏再转竖屏」闪屏。**不要改用资源引用**——系统解析 Manifest 不套用限定符,会导致平板取到竖屏值并触发 AutoSize 放大 +- **AutoSize 基准**: 横屏 1152×720 / 手机竖屏 390×844 / 平板竖屏 720×1280 +- **手机端资源**: `phone_*` 配色 + `bg_phone_*` drawable + 手机版公共标题栏 + +> ⚠️ 禁止用「不同文件名 + 代码判断」切换布局,会生成两个 Binding 类导致运行时 `ClassCastException`。 +> 详见 [`documents/5.5寸手持端适配技术方案.md`](documents/5.5寸手持端适配技术方案.md) 与 `CLAUDE.md` 对应章节。 + +## 🚀 技术栈 + +### 核心框架 +- **Kotlin**: 1.6.21 + Coroutines 1.6.0 +- **Jetpack**: ViewModel、LiveData、DataBinding +- **网络**: Retrofit 2.6.1 + OkHttp 3.12.12 +- **JSON**: FastJSON 1.2.73 + Gson 2.10.1 + +### UI相关 +- **Material Design**: Material Components +- **屏幕适配**: AutoSize 1.2.+ (横屏1152dp × 720dp) +- **下拉刷新**: SmartRefreshLayout 2.0.3 +- **图表**: MPAndroidChart (定制版) +- **弹窗**: XPopup 2.9.19 +- **图片**: Glide 4.15.1 + PictureSelector v3.11.2 + +### 功能组件 +- **路由**: ARouter 1.5.2 +- **扫码**: ZXing 2.2.9 +- **权限**: AndPermission 2.0.2 +- **打印**: 佳博SDK 2.0.4 +- **日志**: Timber 5.0.1 + +## 💼 核心业务模块 + +### 国内出港 (module_gnc) +货物收运、复磅称重、转运管理、出库装机、仓库管理、数据统计 + +### 国内进港 (module_gnj) +舱单管理、卸机入库、出库提货、移库管理、货物交接、实时查询 + +### 国际出港 (module_gjc) +国际货物收运、板箱组装、ULD容器管理、复磅称重、仓储移库 + +### 国际进港 (module_gjj) +国际舱单管理、报文解析、理货管理、出库操作、货物交接 + +### 支持模块 +- **航班管理** (module_hangban): 航班查询、航班统计 +- **货物追踪** (module_cargo): 货物状态追踪、运输日志 +- **监装监卸** (module_mit): 监装监卸管理 +- **PDA功能** (module_p): PDA专用功能 +- **蓝牙打印** (Printer): 佳博打印机SDK集成 + +## 📦 项目结构 + +``` +aerologic-app/ +├── app/ # 应用壳层,整合所有业务模块 +├── module_base/ # 核心基础库,提供所有通用能力 +│ ├── base/ # MVVM基类 +│ ├── http/ # 网络请求框架 +│ ├── ui/weight/ # 统一UI组件 +│ ├── ktx/ # Kotlin扩展函数 +│ ├── bean/ # 数据模型 +│ ├── util/ # 工具类(含 DeviceUtil 设备形态判定) +│ └── router/ # ARouter路由常量 +├── module_gnc/ # 国内出港业务 +├── module_gnj/ # 国内进港业务 +├── module_gjc/ # 国际出港业务 +├── module_gjj/ # 国际进港业务 +├── module_hangban/ # 航班查询管理 +├── module_cargo/ # 货物追踪查询 +├── module_mit/ # 监装监卸管理 +├── module_p/ # PDA专用功能 +├── Printer/ # 蓝牙打印模块 +├── MPChartLib/ # 定制图表库 +├── documents/ # 设计稿、报价单、技术方案文档 +├── CLAUDE.md # 详细开发指南 +└── README.md # 项目说明文档 +``` + +各业务模块内的布局按设备形态分目录存放: + +``` +module_gjc/src/main/res/ +├── layout/ # 手机布局(5.5 寸竖屏,兜底) +└── layout-sw600dp/ # 平板布局(10 寸横屏) +``` + +> 两目录下**同名**的布局是同一布局的资源变体,系统按屏幕最小宽度自动选择。 +> 尚未适配手机的页面,布局保留在 `layout/` 即可(两端共用),支持渐进式适配。 + +## 🚀 快速开始 + +### 环境要求 + +- **IDE**: Android Studio Arctic Fox (2020.3.1) 或更高版本 +- **JDK**: 1.8 +- **Gradle**: 7.3.3 +- **Kotlin**: 1.6.21 + +### 依赖配置 + +如遇依赖下载问题: + +1. 下载 gradle-7.3.3-bin.zip + - 百度网盘: https://pan.baidu.com/s/18wsuGRlNxjMYbxLhBH9yeg + - 提取码: 1029 + +2. 配置Gradle: + - Settings → Build, Execution, Deployment → Build Tools → Gradle + - 解压并替换到 "Gradle user home" 目录 + +### 构建项目 + +```bash +# 克隆项目 +git clone [repository-url] +cd aerologic-app + +# 清理构建 +./gradlew clean + +# 构建Debug版本 +./gradlew assembleDebug + +# 构建Release版本(已签名) +./gradlew assembleRelease + +# 安装到设备 +./gradlew installDebug +``` + +### 组件化开发模式 + +支持模块独立运行调试: + +1. 编辑 `gradle.properties` +2. 设置 `isBuildModule=true` (独立模块) 或 `false` (集成模式) +3. Sync项目并运行对应模块 + +## ⚙️ 配置说明 + +### 网络配置 + +服务器地址配置位置: +- **文件**: `module_base/src/main/res/values/strings.xml` +- **主服务器**: `system_url_inner` +- **地磅服务器**: `weight_url` +- **运行时**: 可通过SharedPreferences动态修改IP地址 + +### 签名配置 + +Release版本签名信息: +- **KeyStore**: `key.jks` (项目根目录) +- **密码**: storePassword/keyPassword均为 `123321` +- **别名**: `key` + +### 网络安全 + +- **超时时间**: 30秒(连接/读取/写入) +- **认证方式**: Bearer Token(自动添加) +- **HTTP支持**: 配置在 `res/xml/network_security_config.xml` + +## 📚 开发文档 + +详细的开发指南请参考 **[CLAUDE.md](./CLAUDE.md)**,包含: + +- ✅ 完整的架构详解(基类、网络、UI组件) +- ✅ 标准开发模板(Activity、ViewModel、ViewHolder) +- ✅ 实际业务示例(列表页、详情页、编辑页) +- ✅ 开发检查清单(7步列表页、4步详情页、5步编辑页) +- ✅ DataBinding适配器(10+种) +- ✅ Kotlin扩展函数(20+种) +- ✅ 常见业务场景实现 + +## 🔄 Git工作流 + +### 分支策略 + +- **develop**: 主开发分支 +- **feature/xxx**: 功能开发分支 +- **release/x.x.x**: 发布分支 +- **hotfix/xxx**: 紧急修复分支 + +### 当前分支 + +- **开发分支**: feature/hefei +- **主分支**: develop(用于PR) + +### 提交规范 + +提交前确保: +- ✅ 代码编译通过 +- ✅ 无明显错误和警告 +- ✅ 遵循项目代码规范 + +## 📋 开发原则 + +1. ✅ **优先使用现有基类和封装**,避免重复造轮子 +2. ✅ **充分利用PadDataLayout和PadSearchLayout组件**,保证UI一致性 +3. ✅ **遵循统一的命名和目录组织规范** +4. ✅ **使用DataBinding简化代码**,减少findViewById +5. ✅ **利用扩展函数处理通用逻辑**(Toast、Dialog、权限等) +6. ✅ **保持架构一致性**,新增业务参考现有模块 + +## 🔐 特性亮点 + +### 1. 高度组件化 +- 业务模块完全解耦,支持独立开发、测试、发布 +- 通过ARouter实现模块间通信,无需直接依赖 + +### 2. 统一UI规范 +- 自定义PadSearchLayout、PadDataLayout组合控件 +- 全局统一的颜色、字体、圆角、间距规范 +- 丰富的DataBinding适配器,简化UI开发 + +### 3. 高效网络框架 +- 协程+Flow的现代化异步方案 +- 统一的请求封装(launchCollect/launchLoadingCollect) +- 自动的Loading管理和错误处理 + +### 4. 完善的基础设施 +- BaseActivity提供扫码、Loading、键盘控制等通用能力 +- BasePageViewModel自动处理分页逻辑 +- CommonAdapter统一列表适配器管理 + +### 5. 丰富的工具扩展 +- 20+ Kotlin扩展函数(Toast、Dialog、JSON、日期等) +- 10+ DataBinding适配器(图片加载、可见性、Shape等) +- 完整的业务开发模板和检查清单 + +## 🛠️ 技术特点 + +- **响应式编程**: Kotlin Coroutines + Flow +- **声明式UI**: DataBinding双向绑定 +- **函数式编程**: Kotlin扩展函数和高阶函数 +- **依赖注入**: 基于ServiceLoader的轻量级方案 +- **模块化路由**: ARouter组件化通信 +- **横屏适配**: AutoSize自动适配1152dp × 720dp +- **蓝牙打印**: 佳博打印机SDK深度集成 +- **二维码扫描**: ZXing高性能扫码 + +## 📄 许可证 + +本项目为企业内部系统,版权归所属公司所有。 + +## ⚠️ 注意事项 + +**重要**: 本项目包含敏感业务信息和配置,仅供授权人员使用,严禁外传。 + +--- + +**文档维护**: 本README提供项目概览和架构信息,详细开发指南请参考 [CLAUDE.md](./CLAUDE.md) diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..f0988cb --- /dev/null +++ b/app/src/debug/AndroidManifest.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 932eace..e0d5ebd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,572 +1,584 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documents/5.5寸手持端-后端字段补充清单.md b/documents/5.5寸手持端-后端字段补充清单.md new file mode 100644 index 0000000..f7328eb --- /dev/null +++ b/documents/5.5寸手持端-后端字段补充清单.md @@ -0,0 +1,55 @@ +# 5.5 寸手持端适配 —— 后端接口补充清单 + +适配手机端时,设计稿要求展示/筛选的部分内容,现有接口没有提供或未生效。 +以下为**实机联调(内网真实数据)验证过**的结论,客户端侧已按设计稿把 UI 与参数都做好, +后端补齐后即可直接生效,客户端基本无需再改。 + +整理时间:2026-07-29  验证环境:内网 `192.168.1.250:8093`,账号 ADMIN + +--- + +## 一、参数已发送但后端未生效(客户端已就绪,等后端支持) + +| 接口 | 参数 | 用途 | 实测现象 | +|------|------|------|----------| +| `IntExpOutHandover/pageQuery`
`IntExpOutHandover/pageQueryTotal` | `hoState`
("0" 待交接 / "1" 已交接) | 出库交接页「待交接 / 已交接」Tab 过滤与角标计数 | 请求体确认携带 `"hoState":"0"` / `"1"`,但两个 Tab 返回**完全相同**的数据;`pageQueryTotal` 的 `wbNumber` 也不随之变化 | +| `IntExpMove/pageQuery`
`IntExpMove/pageQueryTotal` | `spCode`
(特码,如 "PER") | 出港移库页筛选弹层「特码」 | 请求体确认携带 `"spCode":"PER"`,但返回结果中仍含特码为 `PEF` 的记录,角标计数也无变化 | + +> 对照参考:同一接口的 `moveState`、`by1`(承运人)、`awbType`(运单类型)**均正常生效** +> (实测承运人填 MU 后待移库数量 67 → 60),因此可以排除客户端传参方式的问题。 +> +> 若贵方使用的参数名与上表不同,请告知正确名称,客户端改一处常量即可。 + +--- + +## 二、接口未返回、设计稿需要展示的字段 + +以下字段目前接口完全不返回,或恒为 `null`。客户端已按设计稿保留完整 UI 结构, +数据为空时统一占位 `-`,后端补齐后自动显示。 + +### 2.1 `IntExpMove/pageQuery`(出港移库) + +| 设计稿位置 | 需要的字段 | 当前状况 | +|------------|-----------|----------| +| 列表卡片第二行「航班信息:20260709/MU2311」 | 航班日期 + 航班号(如 `fdate` / `fno`) | **接口无任何航班相关字段** | +| 详情页「移库信息」卡片 —— 移库人 | 移库人**姓名**(现只有 `opId`) | `opId` 恒为 `null`,且即便有值也是 ID 而非姓名 | +| 详情页「移库信息」卡片 —— 移库时间 | `opdate` | 恒为 `null`,**已移库记录也是 null** | +| 详情页蓝色表头右侧时间戳 | 同上 `opdate` | 同上 | +| 详情页类型行右侧「普通货物运输」 | `businessType` 或 `cargoType` | 两者均恒为 `null` | + +### 2.2 说明 + +- 出库交接页的详情所需字段(板型、库位、复磅人/时间等)接口均已返回,无需补充。 +- 移库详情页红色标签绑的是 `awbTypeName`(真实值形如「国际出港(国际直航)」),已正常。 + 设计稿上写的「国际进港」经判断为设计稿笔误(该页属国际出港),未按字面实现。 + +--- + +## 三、附:字典接口调用口径(客户端已按此对齐,仅作备忘) + +`typeCode/getSpecialCodeByParam`(特码字典): + +- `flag=1`(国际)+ `ieFlag=""`(**留空**)→ 正常返回 RXE/PER/PEM/PEF/LDP/GJJ/DGR 等 +- `flag=1` + `ieFlag="E"` → 返回 `"data": []` 空数组 + +国际出港各页面统一使用 `ieFlag=""`。如该行为非预期,请后端确认 `ieFlag` 的取值约定。 diff --git a/documents/5.5寸手持端设计文件/00_全部入口总览.html b/documents/5.5寸手持端设计文件/00_全部入口总览.html new file mode 100644 index 0000000..2907b32 --- /dev/null +++ b/documents/5.5寸手持端设计文件/00_全部入口总览.html @@ -0,0 +1,195 @@ + + + + +5.5 寸手持端设计稿 · 全部入口总览 + + + + +
+

5.5 寸手持端设计稿 · 全部入口总览 + 共 11 个业务入口 · 单机画布 390 × 844 +

+
+ + + + + + + +
+
+ +
+ + + + diff --git a/documents/5.5寸手持端设计文件/01_ULD管理/ULD管理.html b/documents/5.5寸手持端设计文件/01_ULD管理/ULD管理.html new file mode 100644 index 0000000..e171678 --- /dev/null +++ b/documents/5.5寸手持端设计文件/01_ULD管理/ULD管理.html @@ -0,0 +1,650 @@ + + + + + +ULD管理 + + + + + +
+
+
+ 09:41 +
+ + + +
+
+
+
+
+ + 返回 +
+

ULD管理

+
+
+
+
+ + + +
+ +
+
+
+ +
+
+
+ + PMC78133363396 +
+
+ 占用 + +
+
+
+
+
+ + 所属航司:CA +
+ +
+ + 来源:空运 +
+
+
+ + 入库时间:2026-07-20 15:59:20 +
+
+
+ +
+
+
+ + PMC78133363397 +
+
+ 可用 + +
+
+
+
+
+ + 所属航司:CA +
+
+ + 来源:空运 +
+
+ +
+ + 入库时间:2026-07-20 15:59:20 +
+
+
+ +
+
+
+ + PMC78133363398 +
+
+ 维修 + +
+
+
+
+
+ + 所属航司:CA +
+
+ + 来源:陆运 +
+
+
+ + 入库时间:2026-07-20 15:59:20 +
+
+
+ +
+
+
+ + PMC78133363399 +
+
+ 占用 + +
+
+
+
+
+ + 所属航司:CA +
+
+ + 来源:空运 +
+
+
+ + 入库时间:2026-07-20 15:59:20 +
+
+
+
+
+
+ +
+
+
+ + +
+
+
+ 已选 0 / 4 项 + +
+
+
+
+ + + + + + + + + + + + + +
+
+ + + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/02_出库交接/出库交接.html b/documents/5.5寸手持端设计文件/02_出库交接/出库交接.html new file mode 100644 index 0000000..718e8cb --- /dev/null +++ b/documents/5.5寸手持端设计文件/02_出库交接/出库交接.html @@ -0,0 +1,715 @@ + + + + + +出库交接 - 移动端原型 + + + + + + + +
+ +
+09:41 +
+ + + +
+
+ + +
+ +
+
+ +返回 +
+

出库交接

+
+
+ + +
+ +
+
+
+ + + +
+ +
+
+ + +
+ + +
+ + +
+ +
+ +
+
+ +
PMC90901CZ
+
+
IMP代码
+
+ +
+ +航班信息:20260706/MU1111 +
+ +
+
+架子车号 +076 +
+
+目的港 +LAX +
+
+装机重 +200kg +
+
+ +
+ +库位:大棚A3 +
+ +
+
+ 查看详情 +
+
+
+ + +
+ +
+
+ +
AKE87865MU
+
+
IMP代码
+
+ +
+ +航班信息:20260706/CA2222 +
+ +
+
+架子车号 +066 +
+
+目的港 +LAX +
+
+装机重 +150kg +
+
+ +
+ +库位:空侧-05 +
+ +
+
+ 查看详情 +
+
+
+ + +
+ +
+
+ +
PMC87678MU
+
+
IMP代码
+
+ +
+ +航班信息:20260707/3U3333 +
+ +
+
+架子车号 +055 +
+
+目的港 +LAX +
+
+装机重 +450kg +
+
+ +
+ +库位:C区-01货位 +
+ +
+
+ 查看详情 +
+
+
+
+ + + +
+ + +
+ +
+
+ + +
+
+
+已选 0 项 + +
+
+
+
+ + +
+ +
+
+ +返回 +
+

板箱详情

+
+
+ +
+ +
+ +
+781-22222620 +
+
+ +
076
+ +
+
+
装机重
+
55
+
+
+
航班日期
+
20260706
+
+
+
航班号
+
MU2231
+
+
+
目的港
+
LAX
+
+
+
IMP代码
+
X
+
+
+
板型
+
QP
+
+
+
库位
+
+1111111 +
+
+
+
备注
+
危险品
+
+
+
+
+ + + +
+
+ + + + + +
+ + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/03_出港计重/detail.html b/documents/5.5寸手持端设计文件/03_出港计重/detail.html new file mode 100644 index 0000000..af16584 --- /dev/null +++ b/documents/5.5寸手持端设计文件/03_出港计重/detail.html @@ -0,0 +1,151 @@ + + + + + +运单详情 + + + + + +
+
+ + +
+ +
+ 09:10 +
+ + + +
+
+ +
+ + + 返回 + +

运单详情

+
+
+ +
+ +
+ +
+
+ 基本信息 +
+ +
+
+ 运单号 + 78111112222 +
+
+ 件数 + 85 +
+
+ 重量 + 156 kg +
+
+ 特码 + DGR +
+
+ 代理 + ATR +
+
+ 航班日期 + 2026-07-03 +
+
+ 航班号 + MU2222 +
+
+ 航程 + PVG - CAN +
+
+ 业务类型 + 普通货物运输 +
+
+ 通道号 + 出港收运1 +
+
+ 品名 + 电子产品 +
+
+ 备注 + 测试 +
+
+
+
+
+ + +
+
+
+ +
+
+ + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/03_出港计重/main.html b/documents/5.5寸手持端设计文件/03_出港计重/main.html new file mode 100644 index 0000000..0e77c7b --- /dev/null +++ b/documents/5.5寸手持端设计文件/03_出港计重/main.html @@ -0,0 +1,419 @@ + + + + + +出港待计重 + + + + + +
+
+ +
+ +
+ 09:10 +
+ + + +
+
+ +
+ +

出港待计重

+
+
+
+ + +
+ +
+
+
+
+ + + +
+ +
+
+ + +
+
+
总票数
+
4
+
+
+
待计重
+
2
+
+
+
计重中
+
2
+
+
+ + +
+ +
+
+
+
+
+ 78133363398 +
+
+ 未计重 + +
+
+
+
+ + 日期:20260721 +
+
+ + 航程:HFE-LAX +
+
+ + 代理:中外运 +
+
+ + 特码:DGR +
+
+
+ +
+
+
+
+ + +
+
+
+
+
+ 78133363399 +
+
+ 计重中 + +
+
+
+
+ + 日期:20260721 +
+
+ + 航程:HFE-LAX +
+
+ + 代理:中外运 +
+
+ + 特码:DGR +
+
+
+ +
+
+
+
+ + +
+
+
+
+
+ 78133363398 +
+
+ 未计重 + +
+
+
+
+ + 日期:20260721 +
+
+ + 航程:HFE-LAX +
+
+ + 代理:中外运 +
+
+ + 特码:DGR +
+
+
+ +
+
+
+
+ + +
+
+
+
+
+ 78133363399 +
+
+ 计重中 + +
+
+
+
+ + 日期:20260721 +
+
+ + 航程:HFE-LAX +
+
+ + 代理:中外运 +
+
+ + 特码:DGR +
+
+
+ +
+
+
+
+
+
+ + +
+
+
+ + + + + + + +
+
+
+

筛选条件

+ +
+
+ +
+ 请选择通道号 + +
+
+
+
+ +
+ MU +
+
+
+ +
+ 请选择运单类型 + +
+
+
+ +
+ 请选择代理人 + +
+
+
+ + +
+
+
+
+
+
+ + + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/03_出港计重/records.html b/documents/5.5寸手持端设计文件/03_出港计重/records.html new file mode 100644 index 0000000..6e1c709 --- /dev/null +++ b/documents/5.5寸手持端设计文件/03_出港计重/records.html @@ -0,0 +1,282 @@ + + + + + +计重记录 - 国际货运管理系统 + + + + + + +
+ +
+09:10 +
+ + + +
+
+ +
+ +

计重记录

+ +
+ +
+ +
+
+
+
+ + + +
+ +
+
+ +
+
+ +
+总票数 +3 +
+ +
+总件数 +1 +
+ +
+总重量 +2 +
+
+
+ +
+ +
+
+78133363396 + + +
+
+ +代理 : 马道 +
+
+
+运抵件数 +
+85件 +
+
+
+运抵重量 +
+1560kg +
+
+
+运抵体积 +
+12.5m³ +
+
+
+
+ +计重人:张三 · 计重时间:2026-07-05 11:45 +
+
+
+查看详情 +
+
+
+ +
+
+78133363398 + + +
+
+ +代理 : 徽远 +
+
+
+运抵件数 +
+60件 +
+
+
+运抵重量 +
+920kg +
+
+
+运抵体积 +
+8.1m³ +
+
+
+
+ +计重人:张三 · 计重时间:2026-07-05 11:45 +
+
+
+查看详情 +
+
+
+
+
+ +
+ + +
+ + +
+
+

筛选条件

+ +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ 全部 + +
+
+
+ +
+ 全部 + +
+
+
+ + +
+
+ +
+ 全部 + +
+
+
+ + +
+
+
+
+ +
+ + + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/03_出港计重/weighing.html b/documents/5.5寸手持端设计文件/03_出港计重/weighing.html new file mode 100644 index 0000000..eca89ab --- /dev/null +++ b/documents/5.5寸手持端设计文件/03_出港计重/weighing.html @@ -0,0 +1,256 @@ + + + + + +开始计重 - 货运管理系统 + + + + + +
+
+ + +
+ +
+ 09:10 +
+ + + +
+
+ +
+ +

开始计重

+
+
+
+ + +
+ +
+
+ +
+ +
+ +
+
+
+ 781333617 +
+ 国际出港 +
+ +
+ +
+ +
+
+

预配件数

+

85

+
+
+

预配重量

+

156 kg

+
+
+

预配体积

+

4.52 m³

+
+
+
+
+
+
+ + +
+ +
+ 通道号* + 请选择通道号 + +
+ +
+ 代理人 + 请选择代理人 + +
+ +
+ 特码 + 请选择特码 + +
+ +
+ 运抵件数 + +
+ +
+ 运抵重量 + +
+ +
+ 运抵体积 + +
+ +
+ 托盘数量 + +
+ +
+ 托盘自重 + +
+ + +
+ 航班日期 + 20260703 +
+
+ 航班号 + MU1111 +
+
+ 航程 + HFE-LAX +
+ + +
+ 业务类型 + 普通货物运输 + +
+ + +
+ 备注 + +
+
+ + +
+
+ + +
+
+
+ + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/03_出港计重/weight-detail.html b/documents/5.5寸手持端设计文件/03_出港计重/weight-detail.html new file mode 100644 index 0000000..5d5a78a --- /dev/null +++ b/documents/5.5寸手持端设计文件/03_出港计重/weight-detail.html @@ -0,0 +1,306 @@ + + + + + +计重明细 + + + + + + +
+
+ + +
+ 09:41 +
+ + + +
+
+ + +
+
+
+ + 返回 +
+

计重明细

+
+ +
+ +
+ +
+ +
+ +
+
+
+ 78133363396 +
+ 国际出港 +
+ +
+ +
+
+
+

总件数

+

85

+
+
+

总重量(kg)

+

1560

+
+
+

托盘总重(kg)

+

54

+
+
+
+
+
+ + +
+
+
+ 运抵件数 + 20 +
+
+ 运抵重量(kg) + 320 +
+
+ 托盘自重(kg) + 18 +
+
+ 计重人 + 张三 +
+
+ 计重时间 + 2026-07-05 10:02:15 +
+
+
+ +
+
+ + +
+
+
+ 运抵件数 + 35 +
+
+ 运抵重量(kg) + 590 +
+
+ 托盘自重(kg) + 18 +
+
+ 计重人 + 张三 +
+
+ 计重时间 + 2026-07-05 10:25:30 +
+
+
+ +
+
+ + +
+
+
+ 运抵件数 + 30 +
+
+ 运抵重量(kg) + 650 +
+
+ 托盘自重(kg) + 18 +
+
+ 计重人 + 张三 +
+
+ 计重时间 + 2026-07-05 11:45:08 +
+
+
+ +
+
+
+
+ + + +
+
+ + + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/04_出港运抵/main.html b/documents/5.5寸手持端设计文件/04_出港运抵/main.html new file mode 100644 index 0000000..ac51214 --- /dev/null +++ b/documents/5.5寸手持端设计文件/04_出港运抵/main.html @@ -0,0 +1,535 @@ + + + + + +出港运抵 + + + + + + + +
+
+
+ 09:41 +
+ + + +
+
+
+
+ + 返回 +
+
+

出港运抵

+
+
+
+
+ +
+
+
+
+ + + +
+ +
+
+ +
+ + +
+ +
+ + + +
+
+
+ +
+ 78133363396 +
+
+
+ 提前运抵 +
+
+
+
代理:马道
+
件数:444
+
重量:150kg
+
航班日期:20260713
+
航班号:MU2033
+
航程:HFE-LAX
+
+
+ +
+ + +
+ + + + + + + + + + +
+
+ + +
+
+
+ + 全选 +
+
+ 已选 0 项 + +
+
+
+
+
+
+ + + +
+
+
+

筛选条件

+ +
+
+
+ +
+ + +
+
+
+ +
+ +
+
+
+ + +
+
+
+ + +
+
+
+ + + +
+
+
+

重置状态

+ +
+
+ + +
+ +
+
+
+ + + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/04_出港运抵/receipt.html b/documents/5.5寸手持端设计文件/04_出港运抵/receipt.html new file mode 100644 index 0000000..73e8d44 --- /dev/null +++ b/documents/5.5寸手持端设计文件/04_出港运抵/receipt.html @@ -0,0 +1,73 @@ + + + + + + +回执内容 + + + + +
+ +
+09:41 +
+ + + +
+
+ +
+ + + 返回 + +回执内容 +
+
+ +
+ +
+

+ + 单一窗口回执内容:45201 空运出口运抵报告传输成功。比对结果为:运抵正常。 +

+

2026-07-10 11:03:38

+
+ +
+

+ + 单一窗口回执内容:45202 空运出口运抵报告传输成功。比对结果为:运抵正常。 +

+

2026-07-10 11:02:15

+
+ +
+

+ + 单一窗口回执内容:45203 空运出口运抵报告传输成功。比对结果为:运抵正常。 +

+

2026-07-10 10:58:42

+
+
+ +
+
+
+
+ + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/04_出港运抵/suborder.html b/documents/5.5寸手持端设计文件/04_出港运抵/suborder.html new file mode 100644 index 0000000..9354985 --- /dev/null +++ b/documents/5.5寸手持端设计文件/04_出港运抵/suborder.html @@ -0,0 +1,413 @@ + + + + + +分单明细 - 出港运抵 + + + + + + + + +
+ +
+ +
+ 09:41 +
+ + + +
+
+ +
+ +

分单明细

+
+
+
+ +
+
+
+ + + +
+ +
+
+ +
+ +
+ +
+
+
+ + 10001 +
+
+ W + 11 +
+
+
+
+ 件数:150 +
+
+ 重量:50kg +
+
+ + +
+ +
+
+
+ + 10002 +
+
+ E + 11 +
+
+
+
+ 件数:120 +
+
+ 重量:40kg +
+
+ + +
+ +
+
+
+ + 10003 +
+
+ 01 + 11 +
+
+
+
+ 件数:174 +
+
+ 重量:60kg +
+
+ + +
+
+
+ +
+
+
+ + 全选 +
+
+ 已选 0 / 3 项 + +
+
+ + + + +
+
+ +
+

筛选条件

+ +
+ +
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+
+ +
+ + +
+
+
+ +
+
+
+
+ + +
+
+ +
+

重置状态

+ +
+ +
+ + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/04_出港运抵/supplement.html b/documents/5.5寸手持端设计文件/04_出港运抵/supplement.html new file mode 100644 index 0000000..4349c2d --- /dev/null +++ b/documents/5.5寸手持端设计文件/04_出港运抵/supplement.html @@ -0,0 +1,175 @@ + + + + + + +补充信息 + + + + + + + + +
+ +
+ +
+09:41 +
+ + + +
+
+ +
+
+ +返回 +
+
+

补充信息

+
+
+
+
+ +
+ +
+
+
+

收货人信息

+
+
+
+ +
+ +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+
+
+

发货人信息

+
+
+
+ +
+ +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+ +
+ + +
+
+
+
+
+ + diff --git a/documents/5.5寸手持端设计文件/05_出港移库/出港移库.html b/documents/5.5寸手持端设计文件/05_出港移库/出港移库.html new file mode 100644 index 0000000..d9a166d --- /dev/null +++ b/documents/5.5寸手持端设计文件/05_出港移库/出港移库.html @@ -0,0 +1,668 @@ + + + + + +出港移库 - 移动端原型 + + + + + + + +
+ +
+ 09:41 +
+ + + +
+
+ + +
+ +
+
+ + 返回 +
+

出港移库

+
+
+ + +
+ +
+
+
+ + + +
+ +
+
+ + +
+ + +
+ + +
+ +
+
+
+ +
78133363573
+
+
+ 待移库 +
+
+
+ + 航班信息:20260709/MU2311 +
+
+
+ 特码 + NOR +
+
+ 件数 + 100件 +
+
+ 重量 + 200kg +
+
+
+ + 出运路径:HFE-NKG-LAX +
+
+
+ 查看详情 +
+
+
+ +
+
+
+ +
78133363574
+
+
+ 待移库 +
+
+
+ + 航班信息:20260709/MU2311 +
+
+
+ 特码 + CTA +
+
+ 件数 + 85件 +
+
+ 重量 + 150kg +
+
+
+ + 出运路径:HFE-PEK-LAX +
+
+
+ 查看详情 +
+
+
+ +
+
+
+ +
78133363575
+
+
+ 待移库 +
+
+
+ + 航班信息:20260709/MU2311 +
+
+
+ 特码 + DHL +
+
+ 件数 + 200件 +
+
+ 重量 + 450kg +
+
+
+ + 出运路径:HFE-NKG-LAX +
+
+
+ 查看详情 +
+
+
+
+ + + +
+ + +
+
+
+ + +
+
+
+ 已选 0 项 + +
+
+
+
+ + +
+
+
+ + 返回 +
+

运单详情

+
+
+
+
+
+ 781-22222620 +
+ + 2026-05-10 08:30 +
+
+
+
+
+ 国际进港 + 普通货物运输 +
+
+
电子元器件
+
+
+
件数
+
55
+
+
+
重量
+
622.00 kg
+
+
+
特码
+
NOR
+
+
+
代理
+
NOR
+
+
+
出运路径
+
HFE-PEK-LAX
+
+
+
承运人
+
MU
+
+
+
+
+ + + +
+
+ + +
+ + +
+
+

筛选条件

+ +
+
+
+ +
+ MU +
+
+
+ +
+ 请选择运单类型 + +
+
+
+ +
+ 请选择特码 + +
+
+
+ + +
+
+
+
+ + + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/06_出港查询/出港查询.html b/documents/5.5寸手持端设计文件/06_出港查询/出港查询.html new file mode 100644 index 0000000..73ed37e --- /dev/null +++ b/documents/5.5寸手持端设计文件/06_出港查询/出港查询.html @@ -0,0 +1,963 @@ + + + + + +出港查询 + + + + + + + +
+ +
+
+ 09:41 +
+ + + +
+
+
+ + +
+
+ +
+ +

筛选条件

+
+ + +
+ +
+ +
+ + +
+
+
+ +
+ + +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+
+ + +
+ + +
+
+ + +
+ +
+ +
+ +

出港查询

+
+ +
+
+ + + +
+ + +
+ +
+
+
总票数
+
4
+
+
+
已入库
+
2
+
+
+
已离港
+
2
+
+
+ +
+ +
+
+
+
+ 78133363396 +
+
+ 已离港 + +
+
+
+
+ + 件数:444 +
+
+ + 重量:555 +
+
+ + 代理人:中外运 +
+
+ + 特码:DGR +
+
+
+ +
+
+
+
+ 78133363397 +
+
+ 已离港 + +
+
+
+
+ + 件数:120 +
+
+ + 重量:320 +
+
+ + 代理人:徽远 +
+
+ + 特码:PER +
+
+
+ +
+
+
+
+ 78133363398 +
+
+ 已入库 + +
+
+
+
+ + 件数:268 +
+
+ + 重量:780 +
+
+ + 代理人:中外运 +
+
+ + 特码:NOR +
+
+
+ +
+
+
+
+ 78133363399 +
+
+ 已离港 + +
+
+
+
+ + 件数:85 +
+
+ + 重量:210 +
+
+ + 代理人:徽远 +
+
+ + 特码:DGR +
+
+
+ +
+
+
+
+ 78133363400 +
+
+ 已离港 + +
+
+
+
+ + 件数:350 +
+
+ + 重量:430 +
+
+ + 代理人:中外运 +
+
+ + 特码:PER +
+
+
+
+
+ + +
+ +
+ +

出港详情

+
+ +
+
+ +
+
+
运单信息
+
仓库信息
+
库位信息
+
+
+ +
+ +
+ +
+
+
+ 基本信息 +
+
+ +
+ 运单号 + +
+
+ 代理人 + +
+ +
+ 特码 + +
+
+ 承运人 + +
+ +
+ 始发站 + +
+
+ 中转站 + +
+
+ 目的站 + +
+
+ UN编号 + +
+ +
+ 锁定状态 +
+ +
+
+
+ 包装类型 + +
+ +
+ 业务类型 + +
+
+ 入库时间 + +
+ +
+ 运单类型 + +
+ +
+ 品名(中) + +
+ +
+ 品名(英) + +
+ +
+ 备注 + +
+
+
+ +
+
+
+ 件重信息 +
+
+
+
运单件数
+
+
+
+
运单重量
+
+
+
+
计费重量
+
+
+
+
入库件数
+
+
+
+
入库重量
+
+
+
+
—
+
—
+
+
+
+ +
+
+
+ 回执信息 +
+
+
+
预配舱单
+
+
+
+
运抵报告
+
+
+
+
海关放行
+
+
+
+
+
+
装载舱单
+
+
+
+
理货报告
+
+
+
+
—
+
—
+
+
+
+
+ + + + +
+
+
+
+ + + + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/06_出港查询/运单追踪.html b/documents/5.5寸手持端设计文件/06_出港查询/运单追踪.html new file mode 100644 index 0000000..7d9fe30 --- /dev/null +++ b/documents/5.5寸手持端设计文件/06_出港查询/运单追踪.html @@ -0,0 +1,139 @@ + + + + + + +国际进港查询 - 物流跟踪 + + + + + + +
+ +
+ +
+09:41 +
+ + + +
+
+ +
+ +

运单追踪

+
+
+
+ +
+ +
+ +
+
+ 78133358743 +
+国际进港 +
+ +
+

+ + + + + 流转状态 +

+
+
+
+ +
+
+
+
+
+
+原始舱单 +放行状态:01 +
+
+2026-07-10 11:03:38 +
+
+
+ +
+
+
+分拣理货 +
+
+ +
+
+
+理货申报 +
+
+ +
+
+
+海关放行 +
+
+ +
+
+
+柜台办结 +
+
+ +
+
+
+提取出库 +
+
+
+
+ + +
+

查询信息已触底

+
+
+ +
+
+
+
+ +ml> \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/07_出港仓库/出港仓库.html b/documents/5.5寸手持端设计文件/07_出港仓库/出港仓库.html new file mode 100644 index 0000000..7dd7e47 --- /dev/null +++ b/documents/5.5寸手持端设计文件/07_出港仓库/出港仓库.html @@ -0,0 +1,932 @@ + + + + + +出港仓库 + + + + + +
+ +
+09:41 +
+ + + +
+
+ +
+
+ +
+ +

筛选条件

+
+ +
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+
+ +
+ + +
+
+ + +
+ +
+ +
+ +

出港仓库

+
+
+ +
+
+
+ + + +
+ +
+
+ +
+
+
总票数
+
8
+
+
+
未清仓
+
4
+
+
+
已清仓
+
4
+
+
+ +
+
+ + + + +
+ + +
+ +
+ +

出港货物

+
+ +
+
+ +
+
+
运单信息
+
仓库信息
+
库位信息
+
+
+ +
+ +
+ +
+
+
+基本信息 +
+
+ +
+运单号 + +
+
+代理人 + +
+ +
+特码 + +
+
+承运人 + +
+ +
+始发站 + +
+
+中转站 + +
+ +
+目的站 + +
+
+UN编号 + +
+ +
+锁定状态 +
+ +
+
+
+包装类型 + +
+ +
+业务类型 + +
+
+入库时间 + +
+ +
+运单类型 + +
+ +
+品名(中) + +
+ +
+品名(英) + +
+ +
+备注 + +
+
+
+ +
+
+
+件重信息 +
+
+
+
运单件数
+
+
+
+
运单重量
+
+
+
+
计费重量
+
+
+
+
入库件数
+
+
+
+
入库重量
+
+
+
+
—
+
—
+
+
+
+ +
+
+
+回执信息 +
+
+
+
预配舱单
+
+
+
+
运抵报告
+
+
+
+
海关放行
+
+
+
+
+
+
装载舱单
+
+
+
+
理货报告
+
+
+
+
+
+ + + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/07_出港仓库/运单追踪.html b/documents/5.5寸手持端设计文件/07_出港仓库/运单追踪.html new file mode 100644 index 0000000..7d9fe30 --- /dev/null +++ b/documents/5.5寸手持端设计文件/07_出港仓库/运单追踪.html @@ -0,0 +1,139 @@ + + + + + + +国际进港查询 - 物流跟踪 + + + + + + +
+ +
+ +
+09:41 +
+ + + +
+
+ +
+ +

运单追踪

+
+
+
+ +
+ +
+ +
+
+ 78133358743 +
+国际进港 +
+ +
+

+ + + + + 流转状态 +

+
+
+
+ +
+
+
+
+
+
+原始舱单 +放行状态:01 +
+
+2026-07-10 11:03:38 +
+
+
+ +
+
+
+分拣理货 +
+
+ +
+
+
+理货申报 +
+
+ +
+
+
+海关放行 +
+
+ +
+
+
+柜台办结 +
+
+ +
+
+
+提取出库 +
+
+
+
+ + +
+

查询信息已触底

+
+
+ +
+
+
+
+ +ml> \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/08_进港仓库/运单追踪.html b/documents/5.5寸手持端设计文件/08_进港仓库/运单追踪.html new file mode 100644 index 0000000..7d9fe30 --- /dev/null +++ b/documents/5.5寸手持端设计文件/08_进港仓库/运单追踪.html @@ -0,0 +1,139 @@ + + + + + + +国际进港查询 - 物流跟踪 + + + + + + +
+ +
+ +
+09:41 +
+ + + +
+
+ +
+ +

运单追踪

+
+
+
+ +
+ +
+ +
+
+ 78133358743 +
+国际进港 +
+ +
+

+ + + + + 流转状态 +

+
+
+
+ +
+
+
+
+
+
+原始舱单 +放行状态:01 +
+
+2026-07-10 11:03:38 +
+
+
+ +
+
+
+分拣理货 +
+
+ +
+
+
+理货申报 +
+
+ +
+
+
+海关放行 +
+
+ +
+
+
+柜台办结 +
+
+ +
+
+
+提取出库 +
+
+
+
+ + +
+

查询信息已触底

+
+
+ +
+
+
+
+ +ml> \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/08_进港仓库/进港仓库.html b/documents/5.5寸手持端设计文件/08_进港仓库/进港仓库.html new file mode 100644 index 0000000..d7e80a7 --- /dev/null +++ b/documents/5.5寸手持端设计文件/08_进港仓库/进港仓库.html @@ -0,0 +1,924 @@ + + + + + +进港仓库 + + + + + +
+ +
+09:41 +
+ + + +
+
+ +
+
+ +
+ +

筛选条件

+
+ +
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+
+ +
+ + +
+
+ + +
+ +
+ +
+ +

进港仓库

+
+
+ +
+
+
+ + + +
+ +
+
+ +
+
+
总票数
+
8
+
+
+
未清仓
+
4
+
+
+
已清仓
+
4
+
+
+ +
+
+ + + + +
+ + +
+ +
+ +

进港货物

+
+ +
+
+ +
+
+
运单信息
+
仓库信息
+
库位信息
+
+
+ +
+ +
+ +
+
+
+基本信息 +
+
+ +
+运单号 + +
+
+代理人 + +
+ +
+特码 + +
+
+承运人 + +
+ +
+始发站 + +
+
+中转站 + +
+ +
+目的站 + +
+
+UN编号 + +
+ +
+锁定状态 +
+ +
+
+
+包装类型 + +
+ +
+业务类型 + +
+
+入库时间 + +
+ +
+运单类型 + +
+ +
+品名(中) + +
+ +
+品名(英) + +
+ +
+备注 + +
+
+
+ +
+
+
+件重信息 +
+
+
+
运单件数
+
+
+
+
运单重量
+
+
+
+
计费重量
+
+
+
+
入库件数
+
+
+
+
入库重量
+
+
+
+
—
+
—
+
+
+
+ +
+
+
+回执信息 +
+
+
+
原始舱单
+
+
+
+
理货报告
+
+
+
+
海关放行
+
+
+
+
+
+
+
+ + + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/09_提取出库/提取出库.html b/documents/5.5寸手持端设计文件/09_提取出库/提取出库.html new file mode 100644 index 0000000..cc8763c --- /dev/null +++ b/documents/5.5寸手持端设计文件/09_提取出库/提取出库.html @@ -0,0 +1,773 @@ + + + + + + +提取出库 - 移动端原型 + + + + + + + +
+ +
+09:41 +
+ + + +
+
+ +
+ +
+
+ +返回 +
+

提取出库

+
+
+ +
+ +
+
+
+ + + +
+ +
+
+ +
+ + +
+ +
+ +
+ +
+
+ +
78133363573
+
+
+ 待出库 +
+
+ +
+ +提货车辆:皖A88909 +
+ +
+
+代理人 +ATR +
+
+件数 +100件 +
+
+重量 +200kg +
+
+ +
+ +库位:A区-03货位 +
+ +
+
+ 查看详情 +
+
+
+ +
+ +
+
+ +
78133363574
+
+
+ 待出库 +
+
+ +
+ +提货车辆:皖A78223 +
+ +
+
+代理人 +CTA +
+
+件数 +85件 +
+
+重量 +150kg +
+
+ +
+ +库位:B区-05货位 +
+ +
+
+ 查看详情 +
+
+
+ +
+ +
+
+ +
78133363575
+
+
+ 待出库 +
+
+ +
+ +提货车辆:皖A67651 +
+ +
+
+代理人 +DHL +
+
+件数 +200件 +
+
+重量 +450kg +
+
+ +
+ +库位:C区-01货位 +
+ +
+
+ 查看详情 +
+
+
+
+ + +
+ +
+ +
+
+ + +
+
+
+已选 0 项 + +
+
+
+
+ +
+ +
+
+ +返回 +
+

运单详情

+
+
+
+ +
+ +
+781-22222620 +
+ +2026-05-10 08:30 +
+
+
+ +
+
+国际进港 +普通货物运输 +
+
+ +
电子元器件
+ +
+
+
件数
+
55
+
+
+
重量
+
622.00 kg
+
+
+
特码
+
NOR
+
+
+
代理
+
ATR
+
+
+
始发港
+
LAX
+
+
+
目的港
+
MU
+
+
+
航班日期
+
20260706
+
+
+
航班号
+
MU1111
+
+
+
库位
+
+1111111 +
+
+
+
提货单号
+
TH20260706001
+
+
+
+
+ + +
+
+ +
+ +
+ +
+

筛选条件

+ +
+ +
+ +
+ +
+ 请选择航班日期 + +
+
+ +
+ +
+ +
+
+ +
+ +
+ 请选择代理人 + +
+
+ +
+ +
+ 请选择特码 + +
+
+
+ + +
+
+
+
+ + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/10_进港查询/运单追踪.html b/documents/5.5寸手持端设计文件/10_进港查询/运单追踪.html new file mode 100644 index 0000000..adbe4c0 --- /dev/null +++ b/documents/5.5寸手持端设计文件/10_进港查询/运单追踪.html @@ -0,0 +1,147 @@ + + + + + + +国际进港查询 - 物流跟踪 + + + + + + +
+ +
+ +
+09:41 +
+ + + +
+
+ +
+ +

运单追踪

+
+
+
+ +
+ +
+ +
+
+ 78133358743 +
+国际进港 +
+ +
+

+ + + + + 流转状态 +

+
+
+
+ + +
+
+
+
+
+
+原始舱单 +放行状态:01 +
+
+2026-07-10 11:03:38 +
+
+
+ +
+
+
+航班落地 +
+
+ +
+
+
+分拣理货 +
+
+ +
+
+
+理货申报 +
+
+ +
+
+
+海关放行 +
+
+ +
+
+
+柜台办结 +
+
+ +
+
+
+提取出库 +
+
+
+
+ + +
+

查询信息已触底

+
+
+ +
+
+
+
+ +ml> \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/10_进港查询/进港查询.html b/documents/5.5寸手持端设计文件/10_进港查询/进港查询.html new file mode 100644 index 0000000..f764f58 --- /dev/null +++ b/documents/5.5寸手持端设计文件/10_进港查询/进港查询.html @@ -0,0 +1,951 @@ + + + + + +进港查询 + + + + + + + +
+ +
+
+ 09:41 +
+ + + +
+
+
+ + +
+
+ +
+ +

筛选条件

+
+ +
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+
+ +
+ + +
+
+ + +
+ +
+ +
+ +

进港查询

+
+ +
+
+ + + +
+ + +
+ +
+
+
总票数
+
4
+
+
+
已入库
+
2
+
+
+
已出库
+
2
+
+
+ +
+ +
+
+
+
+ 78133363396 +
+
+ 已出库 + +
+
+
+
+ + 件数:444 +
+
+ + 重量:555 +
+
+ + 代理人:中外运 +
+
+ + 特码:DGR +
+
+
+ +
+
+
+
+ 78133363397 +
+
+ 已出库 + +
+
+
+
+ + 件数:120 +
+
+ + 重量:320 +
+
+ + 代理人:徽远 +
+
+ + 特码:PER +
+
+
+ +
+
+
+
+ 78133363398 +
+
+ 已入库 + +
+
+
+
+ + 件数:268 +
+
+ + 重量:780 +
+
+ + 代理人:中外运 +
+
+ + 特码:NOR +
+
+
+ +
+
+
+
+ 78133363399 +
+
+ 已出库 + +
+
+
+
+ + 件数:85 +
+
+ + 重量:210 +
+
+ + 代理人:徽远 +
+
+ + 特码:DGR +
+
+
+ +
+
+
+
+ 78133363400 +
+
+ 已出库 + +
+
+
+
+ + 件数:350 +
+
+ + 重量:430 +
+
+ + 代理人:中外运 +
+
+ + 特码:PER +
+
+
+
+
+ + +
+ +
+ +

进港货物

+
+ +
+
+ +
+
+
运单信息
+
仓库信息
+
库位信息
+
+
+ +
+ +
+ +
+
+
+ 基本信息 +
+
+ +
+ 运单号 + +
+
+ 代理人 + +
+ +
+ 特码 + +
+
+ 承运人 + +
+ +
+ 始发港 + +
+
+ 中转站 + +
+ +
+ 目的站 + +
+
+ UN编号 + +
+ +
+ 锁定状态 +
+ +
+
+
+ 包装类型 + +
+ +
+ 业务类型 + +
+
+ 出库时间 + +
+ +
+ 运单类型 + +
+ +
+ 品名(中) + +
+ +
+ 品名(英) + +
+ +
+ 备注 + +
+
+
+ +
+
+
+ 件重信息 +
+
+
+
运单件数
+
+
+
+
运单重量
+
+
+
+
计费重量
+
+
+
+
已出库件数
+
+
+
+
已出库重量
+
+
+
+
—
+
—
+
+
+
+ +
+
+
+ 回执信息 +
+
+
+
原始舱单
+
+
+
+
理货报告
+
+
+
+
海关放行
+
+
+
+
+
+
+
+ + + + +
+
+
+
+ + + + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/11_进港移库/photo.html b/documents/5.5寸手持端设计文件/11_进港移库/photo.html new file mode 100644 index 0000000..b41cd69 --- /dev/null +++ b/documents/5.5寸手持端设计文件/11_进港移库/photo.html @@ -0,0 +1,134 @@ + + + + + +拍照上传 + + + + + + +
+ +
+ 09:41 +
+ + + +
+
+ + +
+
+ + 返回 +
+

拍照上传

+
+
+ + +
+
+
+

运单照片上传

+
+ +
+ + + +
+ + +
+
+
+
+ + + + + \ No newline at end of file diff --git a/documents/5.5寸手持端设计文件/11_进港移库/进港移库.html b/documents/5.5寸手持端设计文件/11_进港移库/进港移库.html new file mode 100644 index 0000000..6daace1 --- /dev/null +++ b/documents/5.5寸手持端设计文件/11_进港移库/进港移库.html @@ -0,0 +1,831 @@ + + + + + +进港移库 - 移动端原型 + + + + + + + +
+ +
+ 09:41 +
+ + + +
+
+ + +
+ +
+
+ + 返回 +
+

进港移库

+
+
+ + +
+ +
+
+
+ + + +
+ +
+
+ + +
+ + +
+ + +
+ +
+
+
+ +
78133363573
+
+
+ 待移库 +
+
+
+ + 航班信息:20260709/MU2311 +
+
+
+ 特码 + NOR +
+
+ 件数 + 100件 +
+
+ 重量 + 200kg +
+
+
+ + 出运路径:HFE-NKG-LAX +
+
+
+ 查看详情 +
+
+ +
+ +
+
+ +
+
+
+ +
78133363574
+
+
+ 待移库 +
+
+
+ + 航班信息:20260709/MU2311 +
+
+
+ 特码 + PER +
+
+ 件数 + 85件 +
+
+ 重量 + 150kg +
+
+
+ + 出运路径:HFE-PEK-LAX +
+
+
+ 查看详情 +
+
+
+ +
+
+ +
+
+
+ +
78133363575
+
+
+ 待移库 +
+
+
+ + 航班信息:20260709/MU2311 +
+
+
+ 特码 + DHL +
+
+ 件数 + 200件 +
+
+ 重量 + 450kg +
+
+
+ + 出运路径:HFE-NKG-LAX +
+
+
+ 查看详情 +
+
+
+ +
+
+
+ + + +
+ + +
+
+
+ + +
+
+
+ 已选 0 项 + +
+
+
+
+ + +
+
+
+ + 返回 +
+

运单详情

+
+
+
+
+
+ 781-22222620 +
+ + 2026-05-10 08:30 +
+
+
+
+
+ 国际进港 + 普通货物运输 +
+
+
电子元器件
+
+
+
件数
+
55
+
+
+
重量
+
622.00 kg
+
+
+
特码
+
NOR
+
+
+
代理
+
NOR
+
+
+
出运路径
+
HFE-PEK-LAX
+
+
+
承运人
+
MU
+
+
+
+
+ + + + + +
+
+ 异常照片 +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+ + +
+
+

筛选条件

+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ +
+
+
+ +
+ 请选择特码 + +
+
+
+ +
+ 请选择特码 + +
+
+
+ + +
+
+
+
+ + + + \ No newline at end of file diff --git a/documents/5.5寸手持端适配技术方案.md b/documents/5.5寸手持端适配技术方案.md new file mode 100644 index 0000000..028362b --- /dev/null +++ b/documents/5.5寸手持端适配技术方案.md @@ -0,0 +1,312 @@ +# 5.5 寸手持端适配技术方案 + +> 适用范围:AirLogistics(航空物流信息管理系统)在现有 10 寸平板横屏基础上,增加 5.5 寸手机竖屏形态。 +> 状态:核心技术已打通并双端实机验证,参考页面「国际出港移库」已完成。 +> 最后更新:2026-07-28 + +--- + +## 一、背景与结论 + +设计稿位于 `documents/5.5寸手持端设计文件/`,共 11 个业务入口、约 66 个界面(37 主页面 + 17 弹层/筛选面板 + 12 详情页 Tab 子页)。手机版是全新 UI,但**功能与交互保持不变**。 + +前置调研结论:**本项目的逻辑与 UI 分离度很好,适配成本可集中在 XML 布局重写。** + +| 层 | 现状 | 手机版可复用性 | +|---|---|---| +| ViewModel(业务逻辑/网络/校验/统计) | 继承 `BaseViewModel`/`BasePageViewModel`,只持有 `MutableLiveData`,不引用 View | 完全复用 | +| Activity | 极薄。如 `IntExpStorageUseActivity` 195 行仅引用 `binding.srl`/`binding.rv`/`binding.viewModel` | 完全复用 | +| ViewHolder | 通过 id 访问控件(`binding.ivIcon` 等) | 保留同名 id 即复用 | +| Adapter | `CommonAdapter` 由 `itemLayoutId` 驱动 | 完全复用 | +| 布局 XML | Pad 横屏专用,三列表单、宽表格式 item | 需全部重写 | +| 公共 UI 组件 | `PadSearchLayout` / `PadDataLayoutNew` / `title_tool_bar` 均为 Pad 形态 | 需新增手机版 | + +两个必须先解决的工程前提: + +1. `app/src/main/AndroidManifest.xml` 中 **95 个 Activity 全部为 `screenOrientation="userLandscape"`**(强制横屏) + —— 现已统一改为 `unspecified`,见下文「屏幕方向」一节 +2. 项目**没有任何资源限定符目录**,只有 `res/layout/` + +--- + +## 二、核心机制:布局按资源限定符自动切换 + +``` +res/layout-sw600dp/activity_xxx.xml ← 平板(最小宽度 >= 600dp,10 寸约 800dp) +res/layout/activity_xxx.xml ← 手机(兜底,5.5 寸约 360~411dp) +``` + +两个变体**同名**,DataBinding 会生成同一个 Binding 基类 + 两个变体实现: + +``` +ActivityIntExpMoveBinding.java 公共基类(Activity 中引用的就是它) +ActivityIntExpMoveBindingImpl.java 手机变体 +ActivityIntExpMoveBindingSw600dpImpl.java 平板变体 +``` + +因此 **Activity / ViewModel / ViewHolder 完全不需要设备判断**,`layoutId()` 与 `itemLayoutId` 保持原样。 + +### 为什么不用「不同文件名 + 代码判断」 + +这是本次实施中被否掉的第一版方案,务必不要走回去: + +```kotlin +// ❌ 错误做法 +override fun layoutId() = + if (DeviceUtil.isPhone()) R.layout.activity_xxx_phone else R.layout.activity_xxx +``` + +`activity_xxx_phone.xml` 生成的是 `ActivityXxxPhoneBinding`,而 `binding` 字段声明的类型是 `ActivityXxxBinding`。 +泛型擦除让**编译期完全不报错**,但一进入该页面就 `ClassCastException` 崩溃。 + +### 变体的强制约束 + +| 约束 | 说明 | 保障方式 | +|---|---|---| +| DataBinding 变量必须完全一致 | 两变体 `` 中 `` 名称与类型相同 | 编译失败 | +| 共用控件 id 双方都要有 | Activity/ViewHolder 引用的 id(`srl`/`rv`/`checkIcon`/`iv_icon` 等) | 见下 | +| 单侧独有 id 自动 `@Nullable` | 只在一个变体存在的 id,基类中为可空字段 | Kotlin 强制 null 检查 | + +实测生成的基类字段可空性(出港移库): + +```java +@NonNull public final TextView btnMove; // 两变体都有 +@NonNull public final ImageView checkIcon; // 两变体都有 +@NonNull public final RecyclerView rv; // 两变体都有 +@NonNull public final SmartRefreshLayout srl; // 两变体都有 +@Nullable public final EditText etWaybillNo; // 仅手机变体 +@Nullable public final PadSearchLayout searchWaybillNo; // 仅平板变体 +``` + +即:**约束由编译器静态保障**,不依赖人工检查。 + +--- + +## 三、已实现的基础设施 + +### 1. `DeviceUtil`(新增) + +`module_base/src/main/java/com/lukouguoji/module_base/util/DeviceUtil.kt` + +按 `smallestScreenWidthDp >= 600` 区分平板/手机。关键点:读取 `Resources.getSystem()`(系统资源)而非应用 Resources,以绕开 AndroidAutoSize 对 density 的动态改写,保证判定稳定。 + +```kotlin +DeviceUtil.isPhone() // 是否手机 +DeviceUtil.isTablet() // 是否平板 +DeviceUtil.describe() // "PHONE(sw=411dp, force=AUTO)",日志排查用 +DeviceUtil.forceMode = DeviceUtil.ForceMode.PHONE // 调试:平板上强制走手机布局 +``` + +`DeviceUtil.layout(padId, phoneId)` 仅用于极少数确实需要代码级判断的场景(如非 DataBinding 布局),**常规页面一律用资源限定符**。 + +### 2. 屏幕方向:Manifest 写 `unspecified` + `BaseActivity` 按形态锁定 + +方案演进过了两轮,两次失败都有明确的实测证据,记录如下以免重蹈。 + +**方案 A(一期,已废弃)**:Manifest 保持 `userLandscape`,靠 `BaseActivity` 在 `onCreate` 里纠正。 +缺陷:手机上「先横屏、约 1 秒后转竖屏」+ Activity 重建。因为 `screenOrientation` 由系统在 +**创建 Activity 窗口时**生效,那时业务代码还没跑,代码只能事后纠正。 + +**方案 B(二期,已废弃)**:Manifest 改 `@integer/screen_orientation`, +`values/`=portrait、`values-sw600dp/`=userLandscape。**看似优雅,实测是错的**: + +> 系统解析 Manifest 属性时用的是**默认配置,不套用设备限定符**,`values-sw600dp/` 永远不会被选中。 +> 于是所有 Activity 都拿到了 `values/` 的竖屏值,平板端出现两个回归: +> 1. 先竖屏、再被 `BaseActivity` 纠正成横屏(把闪屏从手机搬到了平板) +> 2. **AutoSize 在竖屏配置下选了平板竖屏基准 720dp**(density = 1280/720 ≈ 1.78, +> 正常应为 1280/1152 ≈ 1.11)→ 交互几次后整个 UI 放大约 1.6 倍 +> +> 验证方法(可复现):把 `values/` 与 `values-sw600dp/` 的取值**互换**,并临时让 +> `lockOrientationByDevice()` 返回 false 以排除运行时纠正,装到平板上看首屏方向 —— +> 结果平板取的是 `values/` 的值,证明限定符被忽略。 + +**方案 C(现行)**:Manifest 一律写 `unspecified`,系统按设备**当前物理方向**建窗口 +(平板横屏摆放 → 横屏起;手机 → 竖屏起,两端起始方向本就正确), +`BaseActivity.applyDeviceOrientation()` 再按形态锁定,因方向一致故不产生二次纠正与重建。 + +```xml + +``` + +全项目 192 处已统一(`module_p` 等 24 处本就是 `portrait` 的 PDA 页面保持不变)。 + +```kotlin +override fun onCreate(savedInstanceState: Bundle?) { + applyDeviceOrientation() // 必须在 super 之前 + super.onCreate(savedInstanceState) + ... +} + +protected open fun applyDeviceOrientation() { + if (!lockOrientationByDevice()) return + requestedOrientation = if (DeviceUtil.isPhone(this)) + ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + else + ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE +} + +protected open fun lockOrientationByDevice(): Boolean = true // 子类可覆写跳过 +``` + +**已知边界**:若平板在启动瞬间被竖持且系统自动旋转开启,仍会先竖后横。 +现场平板为横屏固定安装,实测无此现象。 + +**验证**:手机冷启动连拍 6 帧全为竖屏;平板冷启动连拍 6 帧全为横屏(1280×800), +登录后多次切换菜单与进出页面,UI 尺寸正常无放大。 + +### 3. AutoSize 设计基准(易漏,后果严重) + +`MyApplication.initAutoSizeConfig()` 原先只按方向切换,现增加手机分支: + +| 场景 | 设计基准 | +|---|---| +| 横屏(平板) | 1152 × 720 dp | +| 竖屏 + 手机 | **390 × 844 dp** ← 本次新增 | +| 竖屏 + 平板 | 720 × 1280 dp | +| PictureSelector | 360 × 480 dp | + +**若手机沿用平板竖屏的 720dp 基准,手机上所有 dp 会被压缩约一半,布局全部错位。** + +### 4. 手机端公共资源 + +| 资源 | 内容 | +|---|---| +| `colors.xml` | `phone_primary`(#2563EB)、`phone_primary_light`、`phone_bg`、`phone_text_title/body/hint`、`phone_divider`、`phone_tag_*` | +| `bg_phone_card.xml` | 列表卡片:白底 + 12dp 圆角 + 0.5dp 边框 | +| `bg_phone_search.xml` | 搜索框:白底 + 12dp 圆角 + 1dp 边框 | +| `bg_phone_btn_primary.xml` | 主按钮:主色实底 + 10dp 圆角 + 按下态 | +| `bg_phone_tag_gray/green.xml` | 状态标签底色 | +| `layout/title_tool_bar.xml` | 手机版标题栏(平板版已移至 `layout-sw600dp/`),保留 `toolbar`/`tool_back`/`title_name` id,`setBackArrow()` 零改动复用 | + +--- + +## 四、手机版 UI 规范 + +| 部位 | 规范 | +|---|---| +| 画布基准 | 390 × 844 dp | +| 顶栏 | 高 48dp,`phone_primary`,左「‹ 返回」,标题居中 18sp 加粗 | +| 页面背景 | `phone_bg` (#F3F4F6) | +| 列表卡片 | `bg_phone_card`,`marginHorizontal=16dp`,`marginTop=12dp`,`padding=14dp` | +| 卡片头行 | 圆形勾选框 20dp(`radiobtn_checked_style`/`radiobtn_unchecked_style`)+ 主字段 15sp 加粗 + 状态标签 | +| 卡片字段 | 两列网格,13sp,`phone_text_body`,行距 8dp | +| 状态标签 | 绿底=已完成 / 灰底=未完成,11sp,高 20dp | +| 搜索行 | 搜索框高 40dp(放大镜 + 输入 + 扫码)+ 右侧筛选按钮 40dp | +| 状态 Tab | 高 42dp,选中文字 `phone_primary` + 底部 28×3dp 指示条 | +| 底部操作条 | 白底 + `elevation=8dp`,全选 + 统计(13sp/11sp 两行)+ 主按钮 | +| 筛选弹层 | 遮罩 `#80000000` + 底部白面板,重置 / 确定各占一半 | + +--- + +## 五、页面改造步骤 + +1. **移动平板布局** + ```bash + mkdir -p module_xxx/src/main/res/layout-sw600dp + git mv module_xxx/src/main/res/layout/activity_xxx.xml module_xxx/src/main/res/layout-sw600dp/activity_xxx.xml + git mv module_xxx/src/main/res/layout/item_xxx.xml module_xxx/src/main/res/layout-sw600dp/item_xxx.xml + ``` +2. **新建手机布局**:在 `res/layout/` 下创建**同名**文件,保持相同 `` 与共用控件 id +3. **Kotlin 侧不动**:`layoutId()`、`itemLayoutId`、ViewHolder 全部保持原样 +4. **纯 UI 交互写在 Activity**,不污染 ViewModel;状态过滤优先复用 ViewModel 既有字段 +5. 手机布局顶部 `` 不变(变体自动切换) + +### 示例:状态 Tab 零 ViewModel 改动 + +出港移库的 `moveState` 字段(`""` 全部 / `"0"` 未移库 / `"1"` 已移库)与查询参数本就存在,Tab 直接复用: + +```kotlin +// IntExpMoveActivity 中新增纯 UI 方法 +fun switchTab(state: String) { + if (viewModel.moveState.value == state) return + viewModel.moveState.value = state + viewModel.searchClick() // 复用原有查询链路 +} +``` + +```xml + +android:textColor="@{`0`.equals(viewModel.moveState) ? @color/phone_primary : @color/phone_text_body}" +``` + +--- + +## 六、参考页面实施结果:国际出港移库 + +| 文件 | 改动 | +|---|---| +| `IntExpMoveViewModel.kt` | **0 行业务改动**(仅补注释) | +| `IntExpMoveViewHolder.kt` | **完全未改** | +| `IntExpMoveActivity.kt` | 仅新增 4 个纯 UI 方法:`switchTab()` / `toggleFilterPanel()` / `resetFilter()` / `confirmFilter()`,以及 `filterPanelVisible` 状态 | +| `layout-sw600dp/activity_int_exp_move.xml` | 原平板布局,内容未变,仅移动目录 | +| `layout-sw600dp/item_int_exp_move.xml` | 同上 | +| `layout/activity_int_exp_move.xml` | 新增手机版 | +| `layout/item_int_exp_move.xml` | 新增手机版 | + +--- + +## 七、双端验证 + +| | 手机模拟器 | 平板模拟器 | +|---|---|---| +| AVD | `Medium_Phone_API_36.1` | `Aerologic_Tablet` | +| 屏幕 | 1080×2400 @420dpi | 1280×800 @160dpi | +| 形态识别 | `PHONE(sw=411dp, force=AUTO)` | `TABLET(sw=800dp, force=AUTO)` | +| 方向 | 竖屏(`unspecified` + BaseActivity 锁定,无闪屏) | 横屏 | +| 加载布局 | 手机版 | 原平板布局,**行为无变化** | +| 交互 | Tab 切换选中态迁移并触发查询;筛选弹层正常弹出/关闭 | — | + +APK 内两套变体均正确打包: + +``` +res/layout-sw600dp-v13/activity_int_exp_move.xml +res/layout-sw600dp-v13/item_int_exp_move.xml +res/layout-sw600dp-v13/title_tool_bar.xml +res/layout/activity_int_exp_move.xml +res/layout/item_int_exp_move.xml +res/layout/title_tool_bar.xml +``` + +### 验证命令 + +```bash +~/Library/Android/sdk/emulator/emulator -list-avds +~/Library/Android/sdk/emulator/emulator -avd Medium_Phone_API_36.1 -no-snapshot-load -no-boot-anim & + +adb -s <设备> install -r -t app/build/outputs/apk/debug/app-debug.apk +adb -s <设备> shell wm size && adb -s <设备> shell wm density +adb -s <设备> logcat -d -s BaseActivity:D # 查看形态识别结果 +adb -s <设备> exec-out screencap -p > /tmp/shot.png +``` + +### 调试便利 + +`app/src/debug/AndroidManifest.xml`(**仅 Debug 生效,不进 Release 包**)用 `tools:replace` 将适配调试页临时置为 `exported="true"`,免去每次登录再逐级点入: + +```bash +adb shell am start -n com.lukouguoji.aerologic/com.lukouguoji.gjc.page.move.IntExpMoveActivity +``` + +新增调试页时在该文件追加对应 `` 即可。 + +--- + +## 八、待办 + +| 项 | 说明 | +|---|---| +| `PhoneDataLayout` 手机版表单组件 | 对标 `PadDataLayoutNew`(319 行 kt)+ `DataLayoutKtx`(404 行)+ `AutoQueryManager`(179 行),支持 INPUT/SPINNER/DATE + required + AutoQuery | +| `PhoneSearchBar` 手机版搜索组件 | 当前手机版搜索框为原生 `EditText`,组件化后恢复运单号 AutoQuery 联想能力 | +| 筛选弹层内控件替换 | 当前仍复用 `PadSearchLayout`(功能完整、视觉待统一) | +| 首页 / 登录 / 我的 | **设计稿缺失**,是手机端使用闭环的前置条件 | + +--- + +## 九、注意事项 + +1. 改动 `BaseActivity` / `BaseBindingActivity` / 公共组件后,**必须在平板上回归**,确认现有平板版行为不变 +2. 未适配手机的页面,布局保留在 `res/layout/` 即可(两端共用),手机上视觉不佳但不会崩溃——支持渐进式适配 +3. 手机版资源统一使用 `phone_*` 颜色与 `bg_phone_*` drawable,禁止直接写死色值 +4. 两个 git 仓库(`aerologic-app` 与 `air-cargo`)为同一份源码的独立副本,适配改动需同步 diff --git a/documents/航空货运APP-5.5寸手持端UI适配-工时报价明细.xlsx b/documents/航空货运APP-5.5寸手持端UI适配-工时报价明细.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b04fdfb8ac063ab97fb273e6b1171ce20fac4ab4 GIT binary patch literal 17364 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

@Kp|qKxHDm0RLJV~F@?&C6$x5dG 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 literal 0 HcmV?d00001 diff --git a/documents/航空货运APP-5.5寸手持端适配报价单(对外).xlsx b/documents/航空货运APP-5.5寸手持端适配报价单(对外).xlsx new file mode 100644 index 0000000000000000000000000000000000000000..8fb6f7bbee51b78abc7c1d62e0c8c0b1a7c4d625 GIT binary patch literal 7521 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 b{#UnBQ$%^3r~v@zk6*FJ_>M*P$KC$`>wllu literal 0 HcmV?d00001 diff --git a/documents/航空货运APP-5.5寸手持端适配报价单.xlsx b/documents/航空货运APP-5.5寸手持端适配报价单.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..0d7820217ae95de1ea3556e1e018fc10415b7ee6 GIT binary patch literal 11067 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%0D)7_LugwA)d|IYn^=!+ghc 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 ISblx_KV9iud;kCd literal 0 HcmV?d00001 diff --git a/module_base/src/main/debug/AndroidManifest.xml b/module_base/src/main/debug/AndroidManifest.xml index f6ebe9f..3bc8754 100644 --- a/module_base/src/main/debug/AndroidManifest.xml +++ b/module_base/src/main/debug/AndroidManifest.xml @@ -1,33 +1,33 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_base/src/main/java/com/lukouguoji/module_base/BaseActivity.kt b/module_base/src/main/java/com/lukouguoji/module_base/BaseActivity.kt index 193ceb2..3efee48 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/BaseActivity.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/BaseActivity.kt @@ -2,6 +2,7 @@ package com.lukouguoji.module_base import android.content.Context import android.content.Intent +import android.content.pm.ActivityInfo import android.content.res.Configuration import android.content.res.Resources import android.net.Uri @@ -26,6 +27,7 @@ import com.yanzhenjie.permission.runtime.Permission import com.yzq.zxinglibrary.android.CaptureActivity import com.yzq.zxinglibrary.bean.ZxingConfig import com.yzq.zxinglibrary.common.Constant +import com.lukouguoji.module_base.util.DeviceUtil import dev.utils.app.HandlerUtils import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -49,15 +51,48 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope { private var timerTask: TimerTask? = null override fun onCreate(savedInstanceState: Bundle?) { + // 必须在 super.onCreate 之前设置,避免进入页面后再旋转造成闪屏与重建 + applyDeviceOrientation() super.onCreate(savedInstanceState) -// requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE setContentView(R.layout.activity_base) - Log.d("BaseActivity", javaClass.simpleName) + Log.d("BaseActivity", "${javaClass.simpleName} ${DeviceUtil.describe()}") ActivityCollector.addActivity(this) ARouter.getInstance().inject(this); /////////必须要写这行,自动注入解析 loadingDialog = LoadingDialog(this) } + /** + * 按设备形态锁定屏幕方向 —— **兜底手段** + * + * 方向的主控权在 Manifest:各 Activity 统一写 + * `android:screenOrientation="@integer/screen_orientation"`, + * 由资源限定符取值(`values/` = portrait,`values-sw600dp/` = userLandscape)。 + * 这样方向在**窗口创建阶段**就已确定,不会出现"先横屏、约 1 秒后转竖屏"的闪屏。 + * + * 本方法只作为安全网:万一某个 Activity 的 Manifest 漏配(仍写死 userLandscape), + * 至少还能在手机上纠正为竖屏——但那种情况下闪屏依旧存在,应当去补 Manifest。 + * + * 子类如需特殊方向(如扫码页),覆写 [lockOrientationByDevice] 返回 false 即可跳过。 + */ + protected open fun applyDeviceOrientation() { + if (!lockOrientationByDevice()) return + try { + requestedOrientation = if (DeviceUtil.isPhone(this)) { + ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + } else { + ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE + } + } catch (e: Exception) { + // 半透明 / 悬浮类 Activity 不允许指定方向,忽略即可 + Log.w("BaseActivity", "setRequestedOrientation failed: ${e.message}") + } + } + + /** + * 是否由基类按设备形态自动锁定方向,默认开启 + */ + protected open fun lockOrientationByDevice(): Boolean = true + override fun onDestroy() { super.onDestroy() job.cancel() diff --git a/module_base/src/main/java/com/lukouguoji/module_base/MyApplication.kt b/module_base/src/main/java/com/lukouguoji/module_base/MyApplication.kt index 4bad6a1..8bdaf41 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/MyApplication.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/MyApplication.kt @@ -13,6 +13,7 @@ import com.cretin.www.cretinautoupdatelibrary.model.UpdateConfig import com.cretin.www.cretinautoupdatelibrary.utils.AppUpdateUtils import com.cretin.www.cretinautoupdatelibrary.utils.SSLUtils.TrustAllHostnameVerifier import com.lukouguoji.module_base.handler.MyCrashHandler +import com.lukouguoji.module_base.util.DeviceUtil import com.lukouguoji.module_base.util.OkHttp3Connection import com.scwang.smart.refresh.footer.ClassicsFooter import com.scwang.smart.refresh.header.ClassicsHeader @@ -79,20 +80,26 @@ class MyApplication : Application() { .setScreenHeight(activity.resources.displayMetrics.heightPixels) //根据屏幕方向,设置设计尺寸 if (activity.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) { - //设置横屏设计尺寸 + //设置横屏设计尺寸(平板) AutoSizeConfig.getInstance() - .setDesignWidthInDp(1152) - .setDesignHeightInDp(720) + .setDesignWidthInDp(DeviceUtil.TABLET_DESIGN_WIDTH_DP_LAND) + .setDesignHeightInDp(DeviceUtil.TABLET_DESIGN_HEIGHT_DP_LAND) } else { if(activity.javaClass.simpleName.startsWith("PictureSelectorSupporterActivity")){ AutoSizeConfig.getInstance() .setDesignWidthInDp(360) .setDesignHeightInDp(480) - }else{ - //设置竖屏设计尺寸 + } else if (DeviceUtil.isPhone(activity)) { + //手机竖屏:按 5.5 寸手持端设计稿画布 390 × 844 换算 + //若沿用平板竖屏的 720 × 1280 基准,手机上所有 dp 会被压缩约一半,布局全部错位 AutoSizeConfig.getInstance() - .setDesignWidthInDp(720) - .setDesignHeightInDp(1280) + .setDesignWidthInDp(DeviceUtil.PHONE_DESIGN_WIDTH_DP) + .setDesignHeightInDp(DeviceUtil.PHONE_DESIGN_HEIGHT_DP) + } else { + //设置竖屏设计尺寸(平板) + AutoSizeConfig.getInstance() + .setDesignWidthInDp(DeviceUtil.TABLET_DESIGN_WIDTH_DP_PORT) + .setDesignHeightInDp(DeviceUtil.TABLET_DESIGN_HEIGHT_DP_PORT) } } } diff --git a/module_base/src/main/java/com/lukouguoji/module_base/base/BaseBindingActivity.kt b/module_base/src/main/java/com/lukouguoji/module_base/base/BaseBindingActivity.kt index 29b8f95..b7eec00 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/base/BaseBindingActivity.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/base/BaseBindingActivity.kt @@ -21,7 +21,17 @@ abstract class BaseBindingActivity : BaseAc override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - //dataBinding初始化 + /* + * dataBinding初始化 + * + * 平板 / 手机双形态的布局切换由 Android 资源限定符自动完成,此处无需分支: + * res/layout-sw600dp/xxx.xml → 平板(最小宽度 >= 600dp) + * res/layout/xxx.xml → 手机(兜底) + * 两个变体同名,DataBinding 会生成同一个 Binding 类,因此 Activity 与 ViewModel 无需改动。 + * + * 注意:不要按「不同文件名 + 代码判断」的方式切换布局, + * 那样会生成两个不同的 Binding 类,泛型擦除下编译期无法发现,运行时必然 ClassCastException。 + */ binding = DataBindingUtil.setContentView(this, layoutId()) binding.lifecycleOwner = this @@ -37,6 +47,9 @@ abstract class BaseBindingActivity : BaseAc /** * 布局ID + * + * 双形态适配时保持同一个 id 即可,具体加载哪份布局由资源限定符决定: + * res/layout-sw600dp/ 平板 res/layout/ 手机 */ abstract fun layoutId(): Int diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/ActionBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/ActionBean.kt index fb29587..6d62372 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/ActionBean.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/ActionBean.kt @@ -1,8 +1,19 @@ -package com.lukouguoji.module_base.bean - -class ActionBean( - val title: String, - val icon: Int, - val key: String = "" -) { -} \ No newline at end of file +package com.lukouguoji.module_base.bean + +/** + * 手持端(手机版)首页菜单项 + * + * @param title 菜单显示名称 + * @param icon 菜单图标 + * @param key 权限串(取 [com.lukouguoji.module_base.common.Constant.AuthName] 中的常量)。 + * 菜单按登录返回的 authList 是否包含该串来决定显不显示 + * @param route ARouter 路由路径。填了就由通用逻辑直接跳转,无需再写 when 分支; + * 留空表示由所在 ViewModel 的 onItemClick 自行处理(module_p 内的 PDA 页面走这条) + */ +class ActionBean( + val title: String, + val icon: Int, + val key: String = "", + val route: String = "" +) { +} diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMove.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMove.kt index 36276c7..deded4b 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMove.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMove.kt @@ -56,4 +56,21 @@ data class GjcMove( var isSelected: Boolean get() = checked.get() set(value) = checked.set(value) + + // ========== 5.5 寸手持端展示辅助字段(仅用于手机版布局,不参与序列化) ========== + + /** 是否已移库(moveState:0-未移交,1-已移交) */ + val isMoved: Boolean + get() = moveState == 1 + + /** 品名:优先中文,为空回退英文 */ + val goodsName: String + get() = goodsCn.ifEmpty { goods } + + /** + * 详情页字段统一空值占位。 + * 接口对 businessType / opdate / opId 等字段常返回 null, + * 直接绑会显示成 "null" 或空白,这里统一成 "-"。 + */ + fun orDash(value: String?): String = if (value.isNullOrEmpty()) "-" else value } diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcUldUseBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcUldUseBean.kt index ccb0add..3bf0e32 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcUldUseBean.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcUldUseBean.kt @@ -108,4 +108,19 @@ class GjcUldUseBean : Serializable { // 复磅状态文本 val wtStatusText: String get() = if (wtDate.isNotEmpty()) "已复磅" else "未复磅" + + // ========== 5.5 寸手持端展示辅助字段(仅用于手机版布局,不参与序列化) ========== + + /** 是否已交接:有交接时间即视为已交接 */ + val isHandovered: Boolean + get() = hoDate.isNotEmpty() + + /** + * IMP 代码是否属于危险品类 —— 决定手机版卡片上 IMP 代码标签是红底还是绿底。 + * + * 依据 IATA IMP 特货代码惯例:以 R 开头(RFL/RRY/REX 等)及 ICE 归为危险品。 + * 若后端另有判定口径,只需改这一处。 + */ + val isDgrDangerous: Boolean + get() = dgrCode.startsWith("R", ignoreCase = true) || dgrCode.equals("ICE", ignoreCase = true) } 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 new file mode 100644 index 0000000..8d1c88c --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneBottomBar.kt @@ -0,0 +1,92 @@ +package com.lukouguoji.module_base.ui.weight.phone + +import android.content.Context +import android.os.Parcelable +import android.util.AttributeSet +import android.util.SparseArray +import android.view.Gravity +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView +import androidx.core.content.ContextCompat +import com.lukouguoji.module_base.R + +/** + * 手机版底部操作条(5.5 寸手持端公共组件) + * + * 结构:全选(圆形勾选框 + 文字)+ 已选统计 + 主操作按钮。 + * 对应设计稿各多选列表页底部的白色操作条。 + * + * XML 用法: + * ```xml + * + * ``` + */ +class PhoneBottomBar @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : LinearLayout(context, attrs, defStyleAttr) { + + val llCheckAll: LinearLayout + val ivCheckAll: ImageView + val tvCount: TextView + val tvAction: TextView + + /** 全选状态(驱动勾选框图标切换) */ + var allChecked: Boolean = false + set(v) { + field = v + ivCheckAll.setImageResource( + if (v) R.drawable.ic_phone_check_round_checked + else R.drawable.ic_phone_check_round_unchecked + ) + } + + /** 已选统计文案,如「已选 3 项」 */ + var countText: String = "" + set(v) { + field = v + tvCount.text = v + } + + /** 主按钮文字 */ + var actionText: String = "" + set(v) { + field = v + tvAction.text = v + } + + init { + orientation = HORIZONTAL + gravity = Gravity.CENTER_VERTICAL + setBackgroundColor(ContextCompat.getColor(context, R.color.white)) + elevation = 8 * resources.displayMetrics.density + val padH = (16 * resources.displayMetrics.density).toInt() + val padV = (14 * resources.displayMetrics.density).toInt() + setPadding(padH, padV, padH, padV) + + inflate(context, R.layout.layout_phone_bottom_bar, this) + + llCheckAll = findViewById(R.id.ll_check_all) + ivCheckAll = findViewById(R.id.iv_check_all) + tvCount = findViewById(R.id.tv_count) + tvAction = findViewById(R.id.tv_action) + } + + /** 只保存/恢复自身状态,避免内部子控件 id 与其他复合组件实例串档 */ + 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/PhoneDataLayout.kt b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneDataLayout.kt new file mode 100644 index 0000000..411a105 --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneDataLayout.kt @@ -0,0 +1,238 @@ +package com.lukouguoji.module_base.ui.weight.phone + +import android.content.Context +import android.os.Parcelable +import android.util.AttributeSet +import android.util.SparseArray +import android.view.View +import android.widget.EditText +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.Spinner +import android.widget.TextView +import androidx.core.widget.doOnTextChanged +import androidx.databinding.InverseBindingListener +import com.lukouguoji.module_base.R +import com.lukouguoji.module_base.adapter.bindAdapter +import com.lukouguoji.module_base.adapter.bindOnSelected +import com.lukouguoji.module_base.interfaces.IOnSpinnerSelected +import com.lukouguoji.module_base.ktx.formatDate +import com.lukouguoji.module_base.ktx.getActivity +import com.lukouguoji.module_base.util.Common +import dev.utils.app.info.KeyValue +import java.util.Calendar + +/** + * 手机版表单 / 筛选项(5.5 寸手持端公共组件) + * + * 结构:上方标题(14sp #374151)+ 下方 40dp 高控件框(白底 + 1px 边框 + 8dp 圆角)。 + * 支持三种形态,由 [type] 决定: + * + * | type | 控件 | 右侧图标 | + * |-----------|-----------|----------| + * | `INPUT` | EditText | 无 | + * | `DATE` | TextView(点击弹日历)| 日历 | + * | `SPINNER` | Spinner | 下箭头 | + * + * XML 用法: + * ```xml + * + * ``` + * + * 手机端专用,与平板端 PadDataLayoutNew 并列存在,互不影响。 + */ +class PhoneDataLayout @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : LinearLayout(context, attrs, defStyleAttr) { + + val tvTitle: TextView + val tvMust: TextView + val llContent: LinearLayout + val et: EditText + val tv: TextView + val spinner: Spinner + val iv: ImageView + + /** 双向绑定回调 */ + var onChangeListener: InverseBindingListener? = null + + /** 输入完成 / 选择完成回调 */ + var refreshCallBack: (() -> Unit)? = null + + var type: PhoneDataLayoutType = PhoneDataLayoutType.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 + bindAdapter(spinner, list, v, R.layout.item_spinner_list_14sp) + } + + var value: String = "" + set(v) { + if (field == v) return + field = v + applyValue() + onChangeListener?.onChange() + } + + var list: List = emptyList() + set(v) { + field = v + bindAdapter(spinner, v, hint, R.layout.item_spinner_list_14sp) + applyValue() + } + + var required: Boolean = false + set(v) { + field = v + tvMust.visibility = if (v) VISIBLE else GONE + } + + var enable: Boolean = true + set(v) { + field = v + llContent.isEnabled = v + et.isEnabled = v + spinner.isEnabled = v + } + + init { + orientation = VERTICAL + inflate(context, R.layout.layout_phone_data_layout, this) + + tvTitle = findViewById(R.id.tv_title) + tvMust = findViewById(R.id.tv_must) + llContent = findViewById(R.id.ll_content) + et = findViewById(R.id.et) + tv = findViewById(R.id.tv) + spinner = findViewById(R.id.spinner) + iv = findViewById(R.id.iv) + + et.doOnTextChanged { text, _, _, _ -> + // 仅 INPUT 形态才回写,避免隐藏的 EditText 被系统状态恢复时误清空值 + if (type == PhoneDataLayoutType.INPUT) { + value = text.toString() + } + } + + bindOnSelected(spinner, object : IOnSpinnerSelected { + override fun onSelected(position: Int) { + value = list.getOrNull(position)?.value ?: "" + refreshCallBack?.invoke() + } + }) + + applyType() + } + + 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) { + PhoneDataLayoutType.INPUT -> { + et.visibility = VISIBLE + tv.visibility = GONE + spinner.visibility = GONE + iv.visibility = GONE + llContent.setOnClickListener(null) + llContent.isClickable = false + } + + PhoneDataLayoutType.DATE -> { + et.visibility = GONE + tv.visibility = VISIBLE + spinner.visibility = GONE + iv.visibility = VISIBLE + iv.setImageResource(R.drawable.ic_phone_calendar) + llContent.setOnClickListener(dateClick) + } + + PhoneDataLayoutType.SPINNER -> { + et.visibility = GONE + tv.visibility = GONE + spinner.visibility = VISIBLE + iv.visibility = VISIBLE + iv.setImageResource(R.drawable.ic_phone_chevron_down) + llContent.setOnClickListener(null) + llContent.isClickable = false + } + } + } + + private fun applyValue() { + when (type) { + PhoneDataLayoutType.INPUT -> { + if (et.text.toString() != value) et.setText(value) + } + + PhoneDataLayoutType.DATE -> { + tv.text = value + } + + PhoneDataLayoutType.SPINNER -> { + if (value.isNotEmpty()) { + val position = list.indexOfFirst { it.value == value } + if (position >= 0) spinner.setSelection(position) + } + } + } + } + + /** + * 同一页面往往放置多个本组件实例,而它们的内部子控件(et / tv / spinner)共用同一套 id。 + * 系统按 id 保存/恢复视图状态会发生跨实例串档(典型表现:日期项被邻近输入框的空文本覆盖)。 + * 这里只保存/恢复自身状态、不下发给子控件;控件取值本就由 ViewModel + DataBinding 持有,无需视图级恢复。 + */ + override fun dispatchSaveInstanceState(container: SparseArray) { + dispatchFreezeSelfOnly(container) + } + + override fun dispatchRestoreInstanceState(container: SparseArray) { + dispatchThawSelfOnly(container) + } + + /** 重置为空值(筛选弹层「重置」按钮使用) */ + fun reset() { + value = "" + if (type == PhoneDataLayoutType.SPINNER && list.isNotEmpty()) { + spinner.setSelection(if (hint.isEmpty()) list.size - 1 else list.size) + } + } +} + +/** [PhoneDataLayout] 支持的控件形态 */ +enum class PhoneDataLayoutType { + INPUT, // 文本输入 + DATE, // 日期选择 + SPINNER, // 下拉选择 +} diff --git a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFilterPanel.kt b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFilterPanel.kt new file mode 100644 index 0000000..ba4c69e --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFilterPanel.kt @@ -0,0 +1,120 @@ +package com.lukouguoji.module_base.ui.weight.phone + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.widget.FrameLayout +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView +import androidx.core.content.ContextCompat +import com.lukouguoji.module_base.R + +/** + * 手机版底部筛选弹层(5.5 寸手持端公共组件) + * + * 半透明遮罩 + 底部白色面板(顶部 20dp 圆角),面板内含标题行、内容插槽、重置/确认按钮行。 + * 对应设计稿各列表页的「筛选条件」弹层。 + * + * **内容插槽**:直接把筛选项(一般是 [PhoneDataLayout])写在本组件标签内即可, + * [onFinishInflate] 会自动把它们移入面板中部,无需关心内部层级: + * + * ```xml + * + * + * + * + * + * + * ``` + * + * 相邻筛选项之间的 20dp 间距由本组件统一施加,使用方无需逐个写 marginTop。 + */ +class PhoneFilterPanel @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : FrameLayout(context, attrs, defStyleAttr) { + + val llPanel: LinearLayout + val llContent: LinearLayout + val tvTitle: TextView + val ivClose: ImageView + val tvReset: TextView + val tvConfirm: TextView + + /** 遮罩点击 / 关闭图标点击回调 */ + private var dismissListener: OnClickListener? = null + + var title: String = "" + set(v) { + field = v + if (v.isNotEmpty()) tvTitle.text = v + } + + /** 弹层显隐 */ + var panelVisible: Boolean = false + set(v) { + field = v + visibility = if (v) VISIBLE else GONE + } + + init { + setBackgroundColor(ContextCompat.getColor(context, R.color.black_tran50)) + visibility = GONE + + inflate(context, R.layout.layout_phone_filter_panel, this) + + llPanel = findViewById(R.id.ll_panel) + llContent = findViewById(R.id.ll_content) + tvTitle = findViewById(R.id.tv_title) + ivClose = findViewById(R.id.iv_close) + tvReset = findViewById(R.id.tv_reset) + tvConfirm = findViewById(R.id.tv_confirm) + + // 遮罩点击关闭;面板自身已 clickable,不会穿透 + setOnClickListener { dismissListener?.onClick(this) } + ivClose.setOnClickListener { dismissListener?.onClick(it) } + } + + /** + * 把 XML 中声明在本组件内的子 View 移入面板内容区,并统一施加 20dp 项间距。 + */ + override fun onFinishInflate() { + super.onFinishInflate() + + // index 0 是内部面板(init 中 inflate 得到),其后才是使用方声明的子 View + val declared = mutableListOf() + for (i in childCount - 1 downTo 1) { + declared.add(0, getChildAt(i)) + removeViewAt(i) + } + + declared.forEachIndexed { index, child -> + llContent.addView(child) + if (index > 0) { + (child.layoutParams as? LinearLayout.LayoutParams)?.let { lp -> + lp.topMargin = (20 * resources.displayMetrics.density).toInt() + child.layoutParams = lp + } + } + } + } + + fun setOnDismiss(listener: OnClickListener?) { + dismissListener = listener + } + + /** 遍历内容区所有 [PhoneDataLayout] 并重置为空值 */ + fun resetAllFields() { + for (i in 0 until llContent.childCount) { + (llContent.getChildAt(i) as? PhoneDataLayout)?.reset() + } + } +} diff --git a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneKvItem.kt b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneKvItem.kt new file mode 100644 index 0000000..aaa1ac0 --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneKvItem.kt @@ -0,0 +1,100 @@ +package com.lukouguoji.module_base.ui.weight.phone + +import android.content.Context +import android.util.AttributeSet +import android.view.Gravity +import android.widget.LinearLayout +import android.widget.TextView +import androidx.core.content.ContextCompat +import com.lukouguoji.module_base.R + +/** + * 手机版详情页字段项(5.5 寸手持端公共组件) + * + * 竖排「小号灰标签(12sp)+ 数值(15sp)」,用于详情页两列信息网格。 + * 对应设计稿「板箱详情」等详情卡片内的字段。 + * + * XML 用法: + * ```xml + * + * ``` + * + * 需要突出的字段(如库位)设 `tag="@{true}"`,数值会渲染为橙色高亮标签。 + */ +class PhoneKvItem @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : LinearLayout(context, attrs, defStyleAttr) { + + val tvTitle: TextView + val tvValue: TextView + + var title: String = "" + set(v) { + field = v + tvTitle.text = v + } + + var value: String = "" + set(v) { + field = v + // 详情页空值统一显示为 "-",与设计稿一致 + tvValue.text = v.ifEmpty { "-" } + applyStyle() + } + + /** 是否以橙色高亮标签样式展示数值 */ + var tag: Boolean = false + set(v) { + field = v + applyStyle() + } + + /** + * 空值不套高亮标签底 —— 否则占位符 "-" 会显示成一个孤零零的橙色小方块。 + */ + private fun applyStyle() { + if (tag && value.isNotEmpty()) { + tvValue.setBackgroundResource(R.drawable.bg_phone_value_orange) + tvValue.setTextColor(ContextCompat.getColor(context, R.color.phone_orange_text)) + tvValue.setTypeface(tvValue.typeface, android.graphics.Typeface.BOLD) + val padH = (4 * resources.displayMetrics.density).toInt() + tvValue.setPadding(padH, 0, padH, 0) + } else { + tvValue.background = null + tvValue.setTextColor(ContextCompat.getColor(context, R.color.phone_text_title)) + tvValue.setPadding(0, 0, 0, 0) + } + } + + init { + orientation = VERTICAL + + tvTitle = TextView(context).apply { + textSize = 12f + setTextColor(ContextCompat.getColor(context, R.color.phone_text_hint)) + } + addView( + tvTitle, + LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) + ) + + tvValue = TextView(context).apply { + textSize = 15f + setTextColor(ContextCompat.getColor(context, R.color.phone_text_title)) + } + addView( + tvValue, + LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT).apply { + topMargin = (2 * resources.displayMetrics.density).toInt() + gravity = Gravity.START + } + ) + } +} diff --git a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneSearchBar.kt b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneSearchBar.kt new file mode 100644 index 0000000..e82b501 --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneSearchBar.kt @@ -0,0 +1,139 @@ +package com.lukouguoji.module_base.ui.weight.phone + +import android.content.Context +import android.os.Parcelable +import android.util.AttributeSet +import android.util.SparseArray +import android.view.View +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.ImageView +import android.widget.LinearLayout +import androidx.core.widget.doOnTextChanged +import androidx.databinding.InverseBindingListener +import com.lukouguoji.module_base.R +import com.lukouguoji.module_base.ktx.setUpperCaseAlphanumericFilter + +/** + * 手机版搜索栏(5.5 寸手持端公共组件) + * + * 结构:圆角搜索框(放大镜 + 输入框 + 扫码图标)+ 右侧圆形筛选按钮。 + * 对应设计稿「5.5寸手持端设计文件」各列表页顶部搜索区。 + * + * XML 用法: + * ```xml + * + * ``` + * + * 说明:与平板端 [com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout] 并列, + * 二者互不影响;手机布局用本组件,平板布局继续用 PadSearchLayout。 + */ +class PhoneSearchBar @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : LinearLayout(context, attrs, defStyleAttr) { + + val llSearch: LinearLayout + val ivSearch: ImageView + val et: EditText + val ivScan: ImageView + val ivFilter: ImageView + + /** 双向绑定回调 */ + var onChangeListener: InverseBindingListener? = null + + /** 键盘「搜索」键 / 扫码完成后触发的查询回调 */ + var searchCallBack: (() -> Unit)? = null + + var value: String = "" + set(v) { + if (field == v) return + field = v + if (et.text.toString() != v) et.setText(v) + onChangeListener?.onChange() + } + + var hint: String = "" + set(v) { + field = v + et.hint = v + } + + /** 是否显示扫码图标(默认显示) */ + var showScan: Boolean = true + set(v) { + field = v + ivScan.visibility = if (v) VISIBLE else GONE + } + + /** 是否显示右侧筛选按钮(默认显示) */ + var showFilter: Boolean = true + set(v) { + field = v + ivFilter.visibility = if (v) VISIBLE else GONE + } + + /** 输入内容强制大写字母数字(运单号 / ULD 编号等场景) */ + var upperCase: Boolean = false + set(v) { + field = v + if (v) et.setUpperCaseAlphanumericFilter() + } + + init { + orientation = HORIZONTAL + gravity = android.view.Gravity.CENTER_VERTICAL + inflate(context, R.layout.layout_phone_search_bar, this) + + llSearch = findViewById(R.id.ll_search) + ivSearch = findViewById(R.id.iv_search) + et = findViewById(R.id.et) + ivScan = findViewById(R.id.iv_scan) + ivFilter = findViewById(R.id.iv_filter) + + et.doOnTextChanged { text, _, _, _ -> + value = text.toString() + } + + // 软键盘「搜索」键触发查询 + et.setOnEditorActionListener { _, actionId, _ -> + if (actionId == EditorInfo.IME_ACTION_SEARCH) { + searchCallBack?.invoke() + true + } else { + false + } + } + } + + /** + * 只保存/恢复自身状态,不下发给内部子控件。 + * 内部 et / iv_* 的 id 在每个实例中相同,交由系统按 id 恢复会跨实例串档; + * 取值本就由 ViewModel + DataBinding 持有,无需视图级恢复。 + */ + override fun dispatchSaveInstanceState(container: SparseArray) { + dispatchFreezeSelfOnly(container) + } + + override fun dispatchRestoreInstanceState(container: SparseArray) { + dispatchThawSelfOnly(container) + } + + /** 供外部(如扫码回调)复用的图标点击入口 */ + fun setOnScanClick(listener: View.OnClickListener?) { + ivScan.setOnClickListener(listener) + } + + fun setOnFilterClick(listener: View.OnClickListener?) { + ivFilter.setOnClickListener(listener) + } +} diff --git a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneStatBox.kt b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneStatBox.kt new file mode 100644 index 0000000..c130e2a --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneStatBox.kt @@ -0,0 +1,108 @@ +package com.lukouguoji.module_base.ui.weight.phone + +import android.content.Context +import android.os.Parcelable +import android.util.AttributeSet +import android.util.SparseArray +import android.view.View +import android.widget.LinearLayout +import android.widget.TextView +import com.lukouguoji.module_base.R + +/** + * 手机版卡片统计框(5.5 寸手持端公共组件) + * + * 浅灰底 + 8dp 圆角,横向等宽 2~4 列,每列为「小号灰标签 + 加粗数值」,列间带竖分隔线。 + * 对应设计稿列表卡片中部的统计区(如「架子车号 / 目的港 / 装机重」)。 + * + * XML 用法(列数由是否传 label 决定,未传的列自动隐藏): + * ```xml + * + * ``` + */ +class PhoneStatBox @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : LinearLayout(context, attrs, defStyleAttr) { + + private val columns: List + private val labels: List + private val values: List + + /** 分隔线(下标 0 对应第 2 列左侧,依次类推) */ + private val dividers: List + + init { + orientation = HORIZONTAL + setBackgroundResource(R.drawable.bg_phone_stat_box) + val pad = (12 * resources.displayMetrics.density).toInt() + setPadding(pad, pad, pad, pad) + + inflate(context, R.layout.layout_phone_stat_box, this) + + columns = listOf( + findViewById(R.id.ll_col1), + findViewById(R.id.ll_col2), + findViewById(R.id.ll_col3), + findViewById(R.id.ll_col4) + ) + labels = listOf( + findViewById(R.id.tv_label1), + findViewById(R.id.tv_label2), + findViewById(R.id.tv_label3), + findViewById(R.id.tv_label4) + ) + values = listOf( + findViewById(R.id.tv_value1), + findViewById(R.id.tv_value2), + findViewById(R.id.tv_value3), + findViewById(R.id.tv_value4) + ) + dividers = listOf( + findViewById(R.id.divider2), + findViewById(R.id.divider3), + findViewById(R.id.divider4) + ) + + // 默认只展示第 1 列,其余待 label 赋值后再显示 + for (i in 1..3) setColumnVisible(i, false) + } + + /** + * 只保存/恢复自身状态。列表中每个卡片都含一个本组件,内部子控件 id 相同, + * 交由系统按 id 恢复会跨实例串档。 + */ + override fun dispatchSaveInstanceState(container: SparseArray) { + dispatchFreezeSelfOnly(container) + } + + override fun dispatchRestoreInstanceState(container: SparseArray) { + dispatchThawSelfOnly(container) + } + + /** 设置第 [index] 列(0 起)的标签,传空则隐藏该列 */ + fun setLabel(index: Int, text: String?) { + if (index !in labels.indices) return + labels[index].text = text.orEmpty() + setColumnVisible(index, !text.isNullOrEmpty()) + } + + /** 设置第 [index] 列(0 起)的数值 */ + fun setValue(index: Int, text: String?) { + if (index !in values.indices) return + values[index].text = text.orEmpty() + } + + private fun setColumnVisible(index: Int, visible: Boolean) { + val flag = if (visible) VISIBLE else GONE + columns[index].visibility = flag + // 第 2~4 列连带其左侧分隔线一起显隐 + if (index in 1..3) dividers[index - 1].visibility = flag + } +} diff --git a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneStatusTab.kt b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneStatusTab.kt new file mode 100644 index 0000000..b16b0b3 --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneStatusTab.kt @@ -0,0 +1,168 @@ +package com.lukouguoji.module_base.ui.weight.phone + +import android.content.Context +import android.util.AttributeSet +import android.view.Gravity +import android.view.View +import android.widget.LinearLayout +import android.widget.TextView +import androidx.core.content.ContextCompat +import androidx.databinding.InverseBindingListener +import com.lukouguoji.module_base.R +import dev.utils.app.info.KeyValue + +/** + * 手机版状态 Tab 条(5.5 寸手持端公共组件) + * + * 每个 Tab = 文字 + 可选角标数字,选中态为「深色加粗文字 + 底部 2dp 全宽指示条」。 + * 对应设计稿各列表页的「待交接 / 已交接」「全部 / 待移库 / 已移库」等状态切换栏。 + * + * XML 用法: + * ```xml + * + * ``` + * + * [tabs] 用 [KeyValue]:`key` 为显示文字,`value` 为写回 [value] 的业务值。 + * [counts] 为与 tabs 等长的角标文案列表,传 null 或空串则该 Tab 不显示角标。 + */ +class PhoneStatusTab @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : LinearLayout(context, attrs, defStyleAttr) { + + /** 双向绑定回调 */ + var onChangeListener: InverseBindingListener? = null + + /** Tab 切换回调(用户点击引起的变化才触发,外部赋值不触发) */ + var tabChangedCallBack: (() -> Unit)? = null + + var tabs: List = emptyList() + set(v) { + field = v + buildTabs() + } + + var counts: List = emptyList() + set(v) { + field = v + refreshState() + } + + var value: String = "" + set(v) { + if (field == v) return + field = v + refreshState() + onChangeListener?.onChange() + } + + init { + orientation = HORIZONTAL + setBackgroundColor(ContextCompat.getColor(context, R.color.white)) + } + + private fun buildTabs() { + removeAllViews() + tabs.forEachIndexed { index, tab -> + addView(createTab(tab, index)) + } + refreshState() + } + + private fun createTab(tab: KeyValue, index: Int): View { + val column = LinearLayout(context).apply { + orientation = VERTICAL + layoutParams = LayoutParams(0, LayoutParams.WRAP_CONTENT, 1f) + setOnClickListener { + val target = tab.value ?: "" + if (value != target) { + value = target + tabChangedCallBack?.invoke() + } + } + } + + // 文字 + 角标 + val row = LinearLayout(context).apply { + orientation = HORIZONTAL + gravity = Gravity.CENTER + layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, dp(42)) + } + row.addView(TextView(context).apply { + id = titleIdOf(index) + text = tab.key + textSize = 14f + setTypeface(typeface, android.graphics.Typeface.BOLD) + }) + row.addView(TextView(context).apply { + id = badgeIdOf(index) + textSize = 11f + gravity = Gravity.CENTER + setBackgroundResource(R.drawable.bg_phone_badge) + setTextColor(ContextCompat.getColor(context, R.color.phone_primary)) + setPadding(dp(6), dp(1), dp(6), dp(1)) + layoutParams = LayoutParams( + LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT + ).apply { marginStart = dp(6) } + }) + column.addView(row) + + // 底部指示条 + column.addView(View(context).apply { + id = indicatorIdOf(index) + layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, dp(2)) + }) + + return column + } + + private fun refreshState() { + tabs.forEachIndexed { index, tab -> + val selected = (tab.value ?: "") == value + + findViewById(titleIdOf(index))?.setTextColor( + ContextCompat.getColor( + context, + if (selected) R.color.phone_text_title else R.color.phone_text_body + ) + ) + + findViewById(indicatorIdOf(index))?.setBackgroundColor( + if (selected) ContextCompat.getColor(context, R.color.phone_text_title) + else android.graphics.Color.TRANSPARENT + ) + + findViewById(badgeIdOf(index))?.apply { + val count = counts.getOrNull(index).orEmpty() + if (count.isEmpty()) { + visibility = GONE + } else { + visibility = VISIBLE + text = count + } + } + } + } + + private fun dp(value: Int): Int = + (value * resources.displayMetrics.density).toInt() + + // 动态生成的子 View 用固定偏移量作为 id,避免与资源 id 冲突 + private fun titleIdOf(index: Int) = ID_BASE_TITLE + index + private fun badgeIdOf(index: Int) = ID_BASE_BADGE + index + private fun indicatorIdOf(index: Int) = ID_BASE_INDICATOR + index + + companion object { + private const val ID_BASE_TITLE = 0x7E100000 + private const val ID_BASE_BADGE = 0x7E200000 + private const val ID_BASE_INDICATOR = 0x7E300000 + } +} 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 new file mode 100644 index 0000000..326658b --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneWidgetKtx.kt @@ -0,0 +1,228 @@ +package com.lukouguoji.module_base.ui.weight.phone + +import android.view.View +import androidx.databinding.BindingAdapter +import androidx.databinding.InverseBindingAdapter +import androidx.databinding.InverseBindingListener +import dev.utils.app.info.KeyValue + +/** + * 5.5 寸手持端公共组件的 DataBinding 适配器集合 + * + * 所有属性均为无命名空间写法(与平板端 PadSearchLayout / PadDataLayoutNew 的用法一致)。 + * 同名属性(hint / value / title / list 等)按控件类型解析,与平板端组件互不冲突。 + */ + +/////////////////////////////////////////////////////////////////////////// +// PhoneSearchBar +/////////////////////////////////////////////////////////////////////////// + +@BindingAdapter("hint", "showScan", "showFilter", "upperCase", requireAll = false) +fun setPhoneSearchBarAttrs( + bar: PhoneSearchBar, + hint: String?, + showScan: Boolean?, + showFilter: Boolean?, + upperCase: Boolean? +) { + hint?.let { bar.hint = it } + showScan?.let { bar.showScan = it } + showFilter?.let { bar.showFilter = it } + upperCase?.let { bar.upperCase = it } +} + +@BindingAdapter("value", requireAll = false) +fun setPhoneSearchBarValue(bar: PhoneSearchBar, value: String?) { + value?.let { bar.value = it } +} + +@InverseBindingAdapter(attribute = "value", event = "valueAttrChanged") +fun getPhoneSearchBarValue(bar: PhoneSearchBar): String = bar.value + +@BindingAdapter("valueAttrChanged", requireAll = false) +fun setPhoneSearchBarValueAttrChanged(bar: PhoneSearchBar, listener: InverseBindingListener) { + bar.onChangeListener = listener +} + +@BindingAdapter("setOnScanClickListener", requireAll = false) +fun setPhoneSearchBarScanClick(bar: PhoneSearchBar, listener: View.OnClickListener?) { + bar.setOnScanClick(listener) +} + +@BindingAdapter("setOnFilterClickListener", requireAll = false) +fun setPhoneSearchBarFilterClick(bar: PhoneSearchBar, listener: View.OnClickListener?) { + bar.setOnFilterClick(listener) +} + +@BindingAdapter("setRefreshCallBack", requireAll = false) +fun setPhoneSearchBarRefreshCallBack(bar: PhoneSearchBar, callBack: (() -> Unit)?) { + bar.searchCallBack = callBack +} + +/////////////////////////////////////////////////////////////////////////// +// PhoneStatusTab +/////////////////////////////////////////////////////////////////////////// + +@BindingAdapter("tabs", requireAll = false) +fun setPhoneStatusTabTabs(tab: PhoneStatusTab, tabs: List?) { + tabs?.let { tab.tabs = it } +} + +@BindingAdapter("counts", requireAll = false) +fun setPhoneStatusTabCounts(tab: PhoneStatusTab, counts: List?) { + tab.counts = counts ?: emptyList() +} + +@BindingAdapter("value", requireAll = false) +fun setPhoneStatusTabValue(tab: PhoneStatusTab, value: String?) { + value?.let { tab.value = it } +} + +@InverseBindingAdapter(attribute = "value", event = "valueAttrChanged") +fun getPhoneStatusTabValue(tab: PhoneStatusTab): String = tab.value + +@BindingAdapter("valueAttrChanged", requireAll = false) +fun setPhoneStatusTabValueAttrChanged(tab: PhoneStatusTab, listener: InverseBindingListener) { + tab.onChangeListener = listener +} + +@BindingAdapter("setOnTabChanged", requireAll = false) +fun setPhoneStatusTabChanged(tab: PhoneStatusTab, callBack: (() -> Unit)?) { + tab.tabChangedCallBack = callBack +} + +/////////////////////////////////////////////////////////////////////////// +// PhoneDataLayout +/////////////////////////////////////////////////////////////////////////// + +@BindingAdapter("title", "hint", "type", "required", "enable", requireAll = false) +fun setPhoneDataLayoutAttrs( + layout: PhoneDataLayout, + title: String?, + hint: String?, + type: PhoneDataLayoutType?, + required: Boolean?, + enable: Boolean? +) { + // type 必须先于 value/hint 生效,否则控件形态与取值分支不匹配 + type?.let { layout.type = it } + title?.let { layout.title = it } + hint?.let { layout.hint = it } + required?.let { layout.required = it } + enable?.let { layout.enable = it } +} + +@BindingAdapter("value", requireAll = false) +fun setPhoneDataLayoutValue(layout: PhoneDataLayout, value: String?) { + value?.let { layout.value = it } +} + +@InverseBindingAdapter(attribute = "value", event = "valueAttrChanged") +fun getPhoneDataLayoutValue(layout: PhoneDataLayout): String = layout.value + +@BindingAdapter("valueAttrChanged", requireAll = false) +fun setPhoneDataLayoutValueAttrChanged( + layout: PhoneDataLayout, + listener: InverseBindingListener +) { + layout.onChangeListener = listener +} + +@BindingAdapter("list", requireAll = false) +fun setPhoneDataLayoutList(layout: PhoneDataLayout, list: List?) { + list?.let { layout.list = it } +} + +@BindingAdapter("setRefreshCallBack", requireAll = false) +fun setPhoneDataLayoutRefreshCallBack(layout: PhoneDataLayout, callBack: (() -> Unit)?) { + layout.refreshCallBack = callBack +} + +/////////////////////////////////////////////////////////////////////////// +// PhoneFilterPanel +/////////////////////////////////////////////////////////////////////////// + +@BindingAdapter("title", "panelVisible", requireAll = false) +fun setPhoneFilterPanelAttrs(panel: PhoneFilterPanel, title: String?, panelVisible: Boolean?) { + title?.let { panel.title = it } + panelVisible?.let { panel.panelVisible = it } +} + +@BindingAdapter("setOnResetClick", requireAll = false) +fun setPhoneFilterPanelResetClick(panel: PhoneFilterPanel, listener: View.OnClickListener?) { + panel.tvReset.setOnClickListener(listener) +} + +@BindingAdapter("setOnConfirmClick", requireAll = false) +fun setPhoneFilterPanelConfirmClick(panel: PhoneFilterPanel, listener: View.OnClickListener?) { + panel.tvConfirm.setOnClickListener(listener) +} + +@BindingAdapter("setOnDismissClick", requireAll = false) +fun setPhoneFilterPanelDismissClick(panel: PhoneFilterPanel, listener: View.OnClickListener?) { + panel.setOnDismiss(listener) +} + +/////////////////////////////////////////////////////////////////////////// +// PhoneBottomBar +/////////////////////////////////////////////////////////////////////////// + +@BindingAdapter("allChecked", "countText", "actionText", requireAll = false) +fun setPhoneBottomBarAttrs( + bar: PhoneBottomBar, + allChecked: Boolean?, + countText: String?, + actionText: String? +) { + allChecked?.let { bar.allChecked = it } + countText?.let { bar.countText = it } + actionText?.let { bar.actionText = it } +} + +@BindingAdapter("setOnAllCheckClick", requireAll = false) +fun setPhoneBottomBarAllCheckClick(bar: PhoneBottomBar, listener: View.OnClickListener?) { + bar.llCheckAll.setOnClickListener(listener) +} + +@BindingAdapter("setOnActionClick", requireAll = false) +fun setPhoneBottomBarActionClick(bar: PhoneBottomBar, listener: View.OnClickListener?) { + bar.tvAction.setOnClickListener(listener) +} + +/////////////////////////////////////////////////////////////////////////// +// PhoneStatBox +/////////////////////////////////////////////////////////////////////////// + +@BindingAdapter( + "label1", "value1", "label2", "value2", + "label3", "value3", "label4", "value4", + requireAll = false +) +fun setPhoneStatBoxAttrs( + box: PhoneStatBox, + label1: String?, value1: String?, + label2: String?, value2: String?, + label3: String?, value3: String?, + label4: String?, value4: String? +) { + box.setLabel(0, label1) + box.setValue(0, value1) + box.setLabel(1, label2) + box.setValue(1, value2) + box.setLabel(2, label3) + box.setValue(2, value3) + box.setLabel(3, label4) + box.setValue(3, value4) +} + +/////////////////////////////////////////////////////////////////////////// +// PhoneKvItem +/////////////////////////////////////////////////////////////////////////// + +@BindingAdapter("title", "value", "tag", requireAll = false) +fun setPhoneKvItemAttrs(item: PhoneKvItem, title: String?, value: String?, tag: Boolean?) { + title?.let { item.title = it } + // tag 需先于 value 生效,确保样式切换后再填内容 + tag?.let { item.tag = it } + item.value = value.orEmpty() +} diff --git a/module_base/src/main/java/com/lukouguoji/module_base/util/DeviceUtil.kt b/module_base/src/main/java/com/lukouguoji/module_base/util/DeviceUtil.kt new file mode 100644 index 0000000..4d4d65e --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/util/DeviceUtil.kt @@ -0,0 +1,116 @@ +package com.lukouguoji.module_base.util + +import android.content.Context +import android.content.res.Resources +import androidx.annotation.LayoutRes +import com.lukouguoji.module_base.MyApplication + +/** + * 设备形态判定工具 + * + * 用于「平板(10 寸横屏)」与「手机(5.5 寸竖屏)」双形态适配: + * 1. 识别当前设备是平板还是手机 + * 2. 提供按形态选择布局的入口(Activity 布局 / RecyclerView item 布局通用) + * 3. 提供手机端 AutoSize 设计基准尺寸常量 + * + * 判定依据:`smallestScreenWidthDp`(最小屏幕宽度,与横竖屏无关,是 Android 官方推荐的设备分类维度) + * - 5.5 寸手机 ≈ 360dp + * - 10 寸平板 ≈ 800dp + * - 分界线取官方标准 600dp + * + * 注意:这里读取的是 [Resources.getSystem](系统资源)而非应用 Resources, + * 目的是绕开 AndroidAutoSize 对 density 的动态改写,保证判定结果稳定。 + */ +object DeviceUtil { + + /** 平板判定阈值:最小屏幕宽度 >= 600dp 视为平板 */ + private const val TABLET_MIN_WIDTH_DP = 600 + + /** 手机端设计稿基准尺寸(对应 5.5 寸手持端设计稿画布 390 × 844) */ + const val PHONE_DESIGN_WIDTH_DP = 390 + const val PHONE_DESIGN_HEIGHT_DP = 844 + + /** 平板端设计稿基准尺寸(沿用现有配置) */ + const val TABLET_DESIGN_WIDTH_DP_LAND = 1152 + const val TABLET_DESIGN_HEIGHT_DP_LAND = 720 + const val TABLET_DESIGN_WIDTH_DP_PORT = 720 + const val TABLET_DESIGN_HEIGHT_DP_PORT = 1280 + + /** + * 调试用:强制指定设备形态 + * + * 开发阶段可在平板上强制走手机布局做验证,正式发布保持 [ForceMode.AUTO]。 + * 用法:`DeviceUtil.forceMode = DeviceUtil.ForceMode.PHONE` + */ + enum class ForceMode { AUTO, PHONE, TABLET } + + @JvmStatic + var forceMode: ForceMode = ForceMode.AUTO + + /** 缓存自动判定结果,避免每次都读 Configuration */ + private var cachedIsTablet: Boolean? = null + + /** + * 是否平板 + * @param context 可不传,默认用 Application 上下文(判定与具体 Activity 无关) + */ + @JvmStatic + @JvmOverloads + fun isTablet(context: Context? = null): Boolean = when (forceMode) { + ForceMode.PHONE -> false + ForceMode.TABLET -> true + ForceMode.AUTO -> cachedIsTablet ?: (smallestWidthDp(context) >= TABLET_MIN_WIDTH_DP) + .also { cachedIsTablet = it } + } + + /** 是否手机 */ + @JvmStatic + @JvmOverloads + fun isPhone(context: Context? = null): Boolean = !isTablet(context) + + /** + * 获取最小屏幕宽度(dp) + * + * 优先读系统资源(不受 AutoSize 影响);异常时回退到应用资源。 + */ + @JvmStatic + @JvmOverloads + fun smallestWidthDp(context: Context? = null): Int { + val fromSystem = Resources.getSystem()?.configuration?.smallestScreenWidthDp ?: 0 + if (fromSystem > 0) return fromSystem + + val res = (context ?: runCatching { MyApplication.context }.getOrNull())?.resources + return res?.configuration?.smallestScreenWidthDp ?: TABLET_MIN_WIDTH_DP + } + + /** + * 按设备形态选择布局 + * + * @param tabletLayout 平板布局(现有布局,必填) + * @param phoneLayout 手机布局;传 0 或未提供时,手机上回退使用平板布局 + * @return 当前设备应加载的布局 id + * + * 用法(ViewModel 中选择 item 布局): + * ``` + * val itemLayoutId = DeviceUtil.layout(R.layout.item_xxx, R.layout.item_xxx_phone) + * ``` + */ + @JvmStatic + @JvmOverloads + fun layout( + @LayoutRes tabletLayout: Int, + @LayoutRes phoneLayout: Int = 0, + context: Context? = null + ): Int = if (phoneLayout != 0 && isPhone(context)) phoneLayout else tabletLayout + + /** 配置发生变化时清空缓存(如分屏、折叠屏形态切换) */ + @JvmStatic + fun clearCache() { + cachedIsTablet = null + } + + /** 设备形态描述,用于日志排查 */ + @JvmStatic + fun describe(): String = + "${if (isTablet()) "TABLET" else "PHONE"}(sw=${smallestWidthDp()}dp, force=$forceMode)" +} diff --git a/module_base/src/main/release/AndroidManifest.xml b/module_base/src/main/release/AndroidManifest.xml index 8201453..5dd7009 100644 --- a/module_base/src/main/release/AndroidManifest.xml +++ b/module_base/src/main/release/AndroidManifest.xml @@ -1,46 +1,46 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_base/src/main/res/drawable/bg_phone_badge.xml b/module_base/src/main/res/drawable/bg_phone_badge.xml new file mode 100644 index 0000000..01467fa --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_badge.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_btn_outline.xml b/module_base/src/main/res/drawable/bg_phone_btn_outline.xml new file mode 100644 index 0000000..a2539f2 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_btn_outline.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_btn_primary.xml b/module_base/src/main/res/drawable/bg_phone_btn_primary.xml new file mode 100644 index 0000000..79bf36f --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_btn_primary.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_card.xml b/module_base/src/main/res/drawable/bg_phone_card.xml new file mode 100644 index 0000000..64c2e9c --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_card.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_card_header_blue.xml b/module_base/src/main/res/drawable/bg_phone_card_header_blue.xml new file mode 100644 index 0000000..29e94e1 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_card_header_blue.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_card_header_green.xml b/module_base/src/main/res/drawable/bg_phone_card_header_green.xml new file mode 100644 index 0000000..8a41698 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_card_header_green.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_dot_green.xml b/module_base/src/main/res/drawable/bg_phone_dot_green.xml new file mode 100644 index 0000000..ac4c39d --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_dot_green.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_icon_round.xml b/module_base/src/main/res/drawable/bg_phone_icon_round.xml new file mode 100644 index 0000000..968fb82 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_icon_round.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_input.xml b/module_base/src/main/res/drawable/bg_phone_input.xml new file mode 100644 index 0000000..ffcec8d --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_input.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_panel_top.xml b/module_base/src/main/res/drawable/bg_phone_panel_top.xml new file mode 100644 index 0000000..8abbc82 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_panel_top.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_search.xml b/module_base/src/main/res/drawable/bg_phone_search.xml new file mode 100644 index 0000000..1a9f98e --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_search.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_stat_box.xml b/module_base/src/main/res/drawable/bg_phone_stat_box.xml new file mode 100644 index 0000000..a65e0b2 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_stat_box.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_tag_gray.xml b/module_base/src/main/res/drawable/bg_phone_tag_gray.xml new file mode 100644 index 0000000..0107085 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_tag_gray.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_tag_green.xml b/module_base/src/main/res/drawable/bg_phone_tag_green.xml new file mode 100644 index 0000000..d4a4a6b --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_tag_green.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_tag_orange.xml b/module_base/src/main/res/drawable/bg_phone_tag_orange.xml new file mode 100644 index 0000000..5c72d67 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_tag_orange.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_tag_red.xml b/module_base/src/main/res/drawable/bg_phone_tag_red.xml new file mode 100644 index 0000000..5ebb1de --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_tag_red.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_value_orange.xml b/module_base/src/main/res/drawable/bg_phone_value_orange.xml new file mode 100644 index 0000000..cc31f77 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_value_orange.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_airplane.xml b/module_base/src/main/res/drawable/ic_phone_airplane.xml new file mode 100644 index 0000000..68b5b06 --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_airplane.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_calendar.xml b/module_base/src/main/res/drawable/ic_phone_calendar.xml new file mode 100644 index 0000000..5cec99e --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_calendar.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_check_circle.xml b/module_base/src/main/res/drawable/ic_phone_check_circle.xml new file mode 100644 index 0000000..656c085 --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_check_circle.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_check_round_checked.xml b/module_base/src/main/res/drawable/ic_phone_check_round_checked.xml new file mode 100644 index 0000000..a3742d5 --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_check_round_checked.xml @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_check_round_unchecked.xml b/module_base/src/main/res/drawable/ic_phone_check_round_unchecked.xml new file mode 100644 index 0000000..d6d4fa9 --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_check_round_unchecked.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_chevron_down.xml b/module_base/src/main/res/drawable/ic_phone_chevron_down.xml new file mode 100644 index 0000000..6ee5c26 --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_chevron_down.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_chevron_right.xml b/module_base/src/main/res/drawable/ic_phone_chevron_right.xml new file mode 100644 index 0000000..5147b47 --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_chevron_right.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_close.xml b/module_base/src/main/res/drawable/ic_phone_close.xml new file mode 100644 index 0000000..d8f7606 --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_close.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_location.xml b/module_base/src/main/res/drawable/ic_phone_location.xml new file mode 100644 index 0000000..572cccb --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_location.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_person.xml b/module_base/src/main/res/drawable/ic_phone_person.xml new file mode 100644 index 0000000..337908f --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_person.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/module_base/src/main/res/layout-sw600dp/title_tool_bar.xml b/module_base/src/main/res/layout-sw600dp/title_tool_bar.xml new file mode 100644 index 0000000..91872c4 --- /dev/null +++ b/module_base/src/main/res/layout-sw600dp/title_tool_bar.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_base/src/main/res/layout/item_spinner_list_14sp.xml b/module_base/src/main/res/layout/item_spinner_list_14sp.xml new file mode 100644 index 0000000..739c7e4 --- /dev/null +++ b/module_base/src/main/res/layout/item_spinner_list_14sp.xml @@ -0,0 +1,15 @@ + + + diff --git a/module_base/src/main/res/layout/layout_phone_bottom_bar.xml b/module_base/src/main/res/layout/layout_phone_bottom_bar.xml new file mode 100644 index 0000000..aa8dc8c --- /dev/null +++ b/module_base/src/main/res/layout/layout_phone_bottom_bar.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_base/src/main/res/layout/layout_phone_data_layout.xml b/module_base/src/main/res/layout/layout_phone_data_layout.xml new file mode 100644 index 0000000..029f007 --- /dev/null +++ b/module_base/src/main/res/layout/layout_phone_data_layout.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_base/src/main/res/layout/layout_phone_filter_panel.xml b/module_base/src/main/res/layout/layout_phone_filter_panel.xml new file mode 100644 index 0000000..1499ea2 --- /dev/null +++ b/module_base/src/main/res/layout/layout_phone_filter_panel.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_base/src/main/res/layout/layout_phone_search_bar.xml b/module_base/src/main/res/layout/layout_phone_search_bar.xml new file mode 100644 index 0000000..a652a92 --- /dev/null +++ b/module_base/src/main/res/layout/layout_phone_search_bar.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + diff --git a/module_base/src/main/res/layout/layout_phone_stat_box.xml b/module_base/src/main/res/layout/layout_phone_stat_box.xml new file mode 100644 index 0000000..54470cd --- /dev/null +++ b/module_base/src/main/res/layout/layout_phone_stat_box.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_base/src/main/res/layout/title_tool_bar.xml b/module_base/src/main/res/layout/title_tool_bar.xml index 91872c4..89a10a3 100644 --- a/module_base/src/main/res/layout/title_tool_bar.xml +++ b/module_base/src/main/res/layout/title_tool_bar.xml @@ -1,42 +1,67 @@ - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + diff --git a/module_base/src/main/res/values/colors.xml b/module_base/src/main/res/values/colors.xml index e893c4e..d88b3ee 100644 --- a/module_base/src/main/res/values/colors.xml +++ b/module_base/src/main/res/values/colors.xml @@ -47,4 +47,31 @@ #80000000 #B3000000 + + #2563EB + #EAF1FE + #F3F4F6 + #1F2937 + #6B7280 + #9CA3AF + #E5E7EB + #F3F4F6 + #6B7280 + #DCFCE7 + #16A34A + #DC2626 + #FFFFFF + #F5F6FA + #F3F4F6 + #DBEAF6 + #374151 + #111827 + #4B5563 + #10B981 + #CBD5E1 + #FFF7ED + #EA580C + #FFEDD5 + #EA580C + \ No newline at end of file diff --git a/module_cargo/src/main/AndroidManifest.xml b/module_cargo/src/main/AndroidManifest.xml index 671905c..f09f4eb 100644 --- a/module_cargo/src/main/AndroidManifest.xml +++ b/module_cargo/src/main/AndroidManifest.xml @@ -1,11 +1,11 @@ - - - - - + + + + + \ No newline at end of file diff --git a/module_cargo/src/main/debug/AndroidManifest.xml b/module_cargo/src/main/debug/AndroidManifest.xml index f4f988b..1959600 100644 --- a/module_cargo/src/main/debug/AndroidManifest.xml +++ b/module_cargo/src/main/debug/AndroidManifest.xml @@ -1,25 +1,25 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_cargo/src/main/release/AndroidManifest.xml b/module_cargo/src/main/release/AndroidManifest.xml index 6814e54..d3796d7 100644 --- a/module_cargo/src/main/release/AndroidManifest.xml +++ b/module_cargo/src/main/release/AndroidManifest.xml @@ -1,17 +1,17 @@ - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/module_gjc/src/main/debug/AndroidManifest.xml b/module_gjc/src/main/debug/AndroidManifest.xml index 79e383b..cbe8e23 100644 --- a/module_gjc/src/main/debug/AndroidManifest.xml +++ b/module_gjc/src/main/debug/AndroidManifest.xml @@ -1,25 +1,25 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverActivity.kt index 447e86d..25e1f83 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverActivity.kt @@ -1,56 +1,96 @@ -package com.lukouguoji.gjc.activity - -import android.app.Activity -import android.content.Intent -import android.os.Bundle -import com.alibaba.android.arouter.facade.annotation.Route -import com.lukouguoji.gjc.R -import com.lukouguoji.gjc.databinding.ActivityIntExpOutHandoverBinding -import com.lukouguoji.gjc.viewModel.IntExpOutHandoverViewModel -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.common.Constant -import com.lukouguoji.module_base.common.ConstantEvent -import com.lukouguoji.module_base.impl.FlowBus -import com.lukouguoji.module_base.impl.observe -import com.lukouguoji.module_base.ktx.addOnItemClickListener -import com.lukouguoji.module_base.router.ARouterConstants - -/** - * 国际出港-出库交接页面 - */ -@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_OUT_HANDOVER) -class IntExpOutHandoverActivity : - BaseBindingActivity() { - - override fun layoutId() = R.layout.activity_int_exp_out_handover - override fun viewModelClass() = IntExpOutHandoverViewModel::class.java - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("国际出港出库交接") - binding.viewModel = viewModel - - // 绑定分页 - viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this) - - // 设置item点击监听 - binding.rv.addOnItemClickListener(viewModel) - - // 监听刷新事件 - FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { viewModel.onItemCheckChanged() } - - FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) { - viewModel.refresh() - } - - // 初始加载数据 - viewModel.refresh() - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - if (requestCode == Constant.RequestCode.ULD && resultCode == Activity.RESULT_OK) { - viewModel.uldNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT) - viewModel.searchClick() - } - } -} +package com.lukouguoji.gjc.activity + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import androidx.databinding.ObservableBoolean +import com.alibaba.android.arouter.facade.annotation.Route +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityIntExpOutHandoverBinding +import com.lukouguoji.gjc.viewModel.IntExpOutHandoverViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.common.ConstantEvent +import com.lukouguoji.module_base.impl.FlowBus +import com.lukouguoji.module_base.impl.observe +import com.lukouguoji.module_base.ktx.addOnItemClickListener +import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil + +/** + * 国际出港-出库交接页面 + * + * 布局 id 不区分设备,平板/手机由资源限定符自动选择: + * layout-sw600dp/activity_int_exp_out_handover.xml(平板) + * layout/activity_int_exp_out_handover.xml(手机) + */ +@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_OUT_HANDOVER) +class IntExpOutHandoverActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_exp_out_handover + override fun viewModelClass() = IntExpOutHandoverViewModel::class.java + + /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ + val filterPanelVisible = ObservableBoolean(false) + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("国际出港出库交接") + binding.viewModel = viewModel + binding.activity = this + + // 手机版专属数据:默认「待交接」Tab、Tab 角标计数、交接人下拉 + // 平板端不调用,查询链路与请求次数与改造前完全一致 + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } + + // 绑定分页 + viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this) + + // 设置item点击监听 + binding.rv.addOnItemClickListener(viewModel) + + // 监听刷新事件 + FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { viewModel.onItemCheckChanged() } + + FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) { + viewModel.refresh() + } + + // 初始加载数据 + viewModel.refresh() + } + + // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 字段) ==================== + + /** 手机版筛选弹层显隐切换 */ + fun toggleFilterPanel() { + filterPanelVisible.set(!filterPanelVisible.get()) + } + + /** + * 手机版筛选:重置 + * + * 只清空弹层内的三个条件(航班日期 / 航班号 / 交接人),不影响 Tab 与顶部搜索框。 + */ + fun resetFilter() { + viewModel.flightDate.value = "" + viewModel.flightNo.value = "" + viewModel.hoId.value = "" + } + + /** 手机版筛选:确认 */ + fun confirmFilter() { + filterPanelVisible.set(false) + viewModel.searchClick() + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == Constant.RequestCode.ULD && resultCode == Activity.RESULT_OK) { + viewModel.uldNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT) + viewModel.searchClick() + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverDetailActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverDetailActivity.kt new file mode 100644 index 0000000..5ece24d --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverDetailActivity.kt @@ -0,0 +1,40 @@ +package com.lukouguoji.gjc.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.google.gson.Gson +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityIntExpOutHandoverDetailBinding +import com.lukouguoji.gjc.viewModel.IntExpOutHandoverDetailViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.GjcUldUseBean +import com.lukouguoji.module_base.common.Constant + +/** + * 国际出港-出库交接「板箱详情」(手机版专属页面) + * + * 由手机版列表卡片的「查看详情」进入;平板端列表布局不含该入口,故不会走到本页。 + */ +class IntExpOutHandoverDetailActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_exp_out_handover_detail + override fun viewModelClass() = IntExpOutHandoverDetailViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("板箱详情") + binding.viewModel = viewModel + viewModel.initOnCreated(intent) + } + + companion object { + @JvmStatic + fun start(context: Context, bean: GjcUldUseBean) { + context.startActivity( + Intent(context, IntExpOutHandoverDetailActivity::class.java) + .putExtra(Constant.Key.DATA, Gson().toJson(bean)) + ) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpMoveViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpMoveViewHolder.kt index e94899a..9a1aa54 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpMoveViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpMoveViewHolder.kt @@ -2,6 +2,7 @@ package com.lukouguoji.gjc.holder import android.view.View import com.lukouguoji.gjc.databinding.ItemIntExpMoveBinding +import com.lukouguoji.gjc.page.move.IntExpMoveDetailActivity import com.lukouguoji.module_base.base.BaseViewHolder import com.lukouguoji.module_base.bean.GjcMove import com.lukouguoji.module_base.common.ConstantEvent @@ -20,6 +21,11 @@ class IntExpMoveViewHolder(view: View) : binding.bean = bean binding.position = position + // 手机版「查看详情」→ 运单详情页(平板变体无此控件,为 null 时跳过) + binding.llDetail?.setOnClickListener { + IntExpMoveDetailActivity.start(itemView.context, bean) + } + // 添加图标点击事件 - 切换选择状态 binding.ivIcon.setOnClickListener { bean.checked.set(!bean.checked.get()) // 反转选择状态 diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpOutHandoverViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpOutHandoverViewHolder.kt index 66b86bd..ce5ac61 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpOutHandoverViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpOutHandoverViewHolder.kt @@ -1,32 +1,41 @@ -package com.lukouguoji.gjc.holder - -import android.view.View -import com.lukouguoji.gjc.databinding.ItemIntExpOutHandoverBinding -import com.lukouguoji.module_base.base.BaseViewHolder +package com.lukouguoji.gjc.holder + +import android.view.View +import com.lukouguoji.gjc.activity.IntExpOutHandoverDetailActivity +import com.lukouguoji.gjc.databinding.ItemIntExpOutHandoverBinding +import com.lukouguoji.module_base.base.BaseViewHolder import com.lukouguoji.module_base.common.ConstantEvent import com.lukouguoji.module_base.impl.FlowBus -import com.lukouguoji.module_base.bean.GjcUldUseBean - -/** - * 国际出港-出库交接 列表项ViewHolder - */ -class IntExpOutHandoverViewHolder(view: View) : - BaseViewHolder(view) { - - override fun onBind(item: Any?, position: Int) { - val bean = getItemBean(item) ?: return - binding.bean = bean - binding.position = position - binding.executePendingBindings() - - // 添加图标点击事件 - 切换选择状态 - binding.ivIcon.setOnClickListener { - // 反转checked状态 - bean.checked.set(!bean.checked.get()) - FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).tryEmit("check_changed") - - // 立即更新UI(图片自动切换) - binding.executePendingBindings() - } - } -} +import com.lukouguoji.module_base.bean.GjcUldUseBean + +/** + * 国际出港-出库交接 列表项ViewHolder + * + * 平板 / 手机共用:布局按资源限定符切换,本类不做设备判断。 + * `llDetail`(查看详情)仅存在于手机变体,平板变体中为 null,因此需判空。 + */ +class IntExpOutHandoverViewHolder(view: View) : + BaseViewHolder(view) { + + override fun onBind(item: Any?, position: Int) { + val bean = getItemBean(item) ?: return + binding.bean = bean + binding.position = position + binding.executePendingBindings() + + // 添加图标点击事件 - 切换选择状态 + binding.ivIcon.setOnClickListener { + // 反转checked状态 + bean.checked.set(!bean.checked.get()) + FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).tryEmit("check_changed") + + // 立即更新UI(图片自动切换) + binding.executePendingBindings() + } + + // 手机版「查看详情」→ 板箱详情页(平板变体无此控件,为 null 时跳过) + binding.llDetail?.setOnClickListener { + IntExpOutHandoverDetailActivity.start(itemView.context, bean) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt index d9edbf7..26dc0a1 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt @@ -4,7 +4,7 @@ import android.app.Activity import android.content.Context import android.content.Intent import android.os.Bundle -import androidx.appcompat.app.AlertDialog +import androidx.databinding.ObservableBoolean import com.alibaba.android.arouter.facade.annotation.Route import com.lukouguoji.gjc.R import com.lukouguoji.gjc.databinding.ActivityIntExpMoveBinding @@ -16,8 +16,10 @@ import com.lukouguoji.module_base.impl.FlowBus import com.lukouguoji.module_base.impl.observe import com.lukouguoji.module_base.ktx.addOnItemClickListener import com.lukouguoji.module_base.ktx.showToast +import com.lukouguoji.module_base.model.ConfirmDialogModel import com.lukouguoji.module_base.model.ScanModel import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil /** * 国际出港-出港移库 @@ -25,14 +27,26 @@ import com.lukouguoji.module_base.router.ARouterConstants @Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_MOVE) class IntExpMoveActivity : BaseBindingActivity() { + // 布局 id 不区分设备,平板/手机由资源限定符自动选择: + // layout-sw600dp/activity_int_exp_move.xml(平板) / layout/activity_int_exp_move.xml(手机) override fun layoutId() = R.layout.activity_int_exp_move + override fun viewModelClass() = IntExpMoveViewModel::class.java + /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ + val filterPanelVisible = ObservableBoolean(false) + override fun initOnCreate(savedInstanceState: Bundle?) { setBackArrow("国际出港移库") binding.viewModel = viewModel binding.activity = this + // 手机版专属数据:默认「待移库」Tab、Tab 角标计数、特码下拉 + // 平板端不调用,查询链路与请求次数与改造前完全一致 + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } + initRecyclerView() initListeners() observeData() @@ -55,8 +69,8 @@ class IntExpMoveActivity : BaseBindingActivity - viewModel.submitMove() - } - .setNegativeButton("取消", null) - .show() + ConfirmDialogModel( + message = "确定要移库选中的 ${selectedItems.size} 条运单吗?", + title = "移库确认" + ) { + viewModel.submitMove() + }.show() } /** diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveDetailActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveDetailActivity.kt new file mode 100644 index 0000000..80b3f91 --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveDetailActivity.kt @@ -0,0 +1,40 @@ +package com.lukouguoji.gjc.page.move + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.google.gson.Gson +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityIntExpMoveDetailBinding +import com.lukouguoji.gjc.viewModel.IntExpMoveDetailViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.GjcMove +import com.lukouguoji.module_base.common.Constant + +/** + * 国际出港移库「运单详情」(手机版专属页面) + * + * 由手机版列表卡片的「查看详情」进入;平板端列表布局不含该入口,故不会走到本页。 + */ +class IntExpMoveDetailActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_exp_move_detail + override fun viewModelClass() = IntExpMoveDetailViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("运单详情") + binding.viewModel = viewModel + viewModel.initOnCreated(intent) + } + + companion object { + @JvmStatic + fun start(context: Context, bean: GjcMove) { + context.startActivity( + Intent(context, IntExpMoveDetailActivity::class.java) + .putExtra(Constant.Key.DATA, Gson().toJson(bean)) + ) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveDetailViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveDetailViewModel.kt new file mode 100644 index 0000000..f411354 --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveDetailViewModel.kt @@ -0,0 +1,25 @@ +package com.lukouguoji.gjc.viewModel + +import android.content.Intent +import androidx.lifecycle.MutableLiveData +import com.google.gson.Gson +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.GjcMove +import com.lukouguoji.module_base.common.Constant + +/** + * 国际出港移库「运单详情」ViewModel(手机版专属页面) + * + * 列表项数据已包含详情页所需全部字段,故直接由列表带入,不额外请求接口。 + */ +class IntExpMoveDetailViewModel : BaseViewModel() { + + val dataBean = MutableLiveData(GjcMove()) + + fun initOnCreated(intent: Intent) { + val json = intent.getStringExtra(Constant.Key.DATA).orEmpty() + if (json.isNotEmpty()) { + dataBean.value = Gson().fromJson(json, GjcMove::class.java) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveViewModel.kt index cf9b62e..d494e50 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveViewModel.kt @@ -14,6 +14,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.util.CheckUtil +import com.lukouguoji.module_base.util.DictUtils import dev.utils.app.info.KeyValue /** @@ -24,10 +25,48 @@ class IntExpMoveViewModel : BasePageViewModel(), IOnItemClickListener { // ========== 搜索字段 ========== val awbType = MutableLiveData("") // 运单类型 val by1 = MutableLiveData("") // 承运人 - val dest1 = MutableLiveData("") // 卸货站 + val dest1 = MutableLiveData("") // 卸货站(仅平板筛选,手机版设计稿无此项) val moveState = MutableLiveData("") // 移库状态 val waybillNo = MutableLiveData("") // 运单号 + // ========== 手机版(5.5 寸手持端)专用 ========== + // 平板布局无对应控件,spCode 恒为空 → 不进请求,平板查询行为与改造前一致 + val spCode = MutableLiveData("") // 特码 + + /** 特码下拉数据(仅手机版筛选弹层使用,由 [initPhoneExtras] 触发加载) */ + val spCodeList = MutableLiveData>(emptyList()) + + /** 手机版状态 Tab 配置(设计稿只有两个 Tab,无「全部」) */ + val moveStateTabs = MutableLiveData( + listOf(KeyValue("待移库", "0"), KeyValue("已移库", "1")) + ) + + /** 手机版状态 Tab 角标(与 [moveStateTabs] 等长) */ + val moveStateCounts = MutableLiveData(listOf("", "")) + + /** 已选数量(手机版底部操作条「已选 N 项」) */ + val selectedCount = MutableLiveData("0") + + /** + * 是否启用手机版专属数据(Tab 角标计数、特码下拉)。 + * 平板端保持 false,不产生任何额外接口请求。 + */ + private var phoneExtrasEnabled = false + + /** + * 开启手机版专属数据:默认停留「待移库」Tab、加载特码下拉、启用 Tab 角标计数。 + * 仅由手机形态的 Activity 调用。 + */ + fun initPhoneExtras() { + phoneExtrasEnabled = true + moveState.value = "0" + // flag=1 国际;ieFlag 必须留空——传 "E" 后端返回空数组, + // 与 GjcWeighingStartViewModel 等既有国际出港页面的调用方式保持一致 + DictUtils.getSpecialCodeList(addAll = false, flag = 1, ieFlag = "") { list -> + spCodeList.postValue(list) + } + } + // ========== 运单类型下拉数据 ========== val awbTypeList = MutableLiveData>().apply { value = listOf( @@ -55,6 +94,8 @@ class IntExpMoveViewModel : BasePageViewModel(), IOnItemClickListener { // ========== 适配器配置 ========== val itemViewHolder = IntExpMoveViewHolder::class.java + + // 布局 id 不区分设备,平板/手机由资源限定符自动选择(layout-sw600dp/ 与 layout/ 下的同名布局) val itemLayoutId = R.layout.item_int_exp_move /** @@ -100,6 +141,8 @@ class IntExpMoveViewModel : BasePageViewModel(), IOnItemClickListener { } else { isAllChecked.value = false } + + selectedCount.value = list.count { it.checked.get() }.toString() } /** @@ -153,6 +196,8 @@ class IntExpMoveViewModel : BasePageViewModel(), IOnItemClickListener { dest1.value?.takeIf { it.isNotEmpty() }?.let { filterParams["dest1"] = it } moveState.value?.takeIf { it.isNotEmpty() }?.let { filterParams["moveState"] = it } waybillNo.value?.takeIf { it.isNotEmpty() }?.let { filterParams["wbNo"] = it } + // 手机版新增筛选维度,平板端恒为空故不参与查询 + spCode.value?.takeIf { it.isNotEmpty() }?.let { filterParams["spCode"] = it } // 列表参数(含分页) val listParams = (filterParams + mapOf( @@ -172,6 +217,33 @@ class IntExpMoveViewModel : BasePageViewModel(), IOnItemClickListener { // 获取统计(后台调用) getTotalData(totalParams) + + // 手机版 Tab 角标计数(平板端不触发,无额外请求) + if (phoneExtrasEnabled) { + loadTabCounts(filterParams) + } + } + + /** + * 加载「待移库 / 已移库」Tab 角标数量。 + * + * 复用统计接口,分别以 moveState=0 / 1 各查一次,并沿用当前其余筛选条件, + * 保证角标与列表口径一致。仅手机版调用。 + */ + private fun loadTabCounts(filterParams: Map) { + listOf("0", "1").forEachIndexed { index, state -> + val params = (filterParams + mapOf("moveState" to state)).toRequestBody() + launchCollect({ NetApply.api.getIntExpMoveTotal(params) }) { + onSuccess = { result -> + val count = (result.data?.wbNumber ?: 0).toString() + val current = moveStateCounts.value?.toMutableList() ?: mutableListOf("", "") + if (index < current.size) { + current[index] = count + moveStateCounts.value = current + } + } + } + } } /** diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverDetailViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverDetailViewModel.kt new file mode 100644 index 0000000..02b398a --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverDetailViewModel.kt @@ -0,0 +1,25 @@ +package com.lukouguoji.gjc.viewModel + +import android.content.Intent +import androidx.lifecycle.MutableLiveData +import com.google.gson.Gson +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.GjcUldUseBean +import com.lukouguoji.module_base.common.Constant + +/** + * 国际出港-出库交接「板箱详情」ViewModel(手机版专属页面) + * + * 列表项数据已包含详情页所需全部字段,故直接由列表带入,不额外请求接口。 + */ +class IntExpOutHandoverDetailViewModel : BaseViewModel() { + + val dataBean = MutableLiveData(GjcUldUseBean()) + + fun initOnCreated(intent: Intent) { + val json = intent.getStringExtra(Constant.Key.DATA).orEmpty() + if (json.isNotEmpty()) { + dataBean.value = Gson().fromJson(json, GjcUldUseBean::class.java) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverViewModel.kt index c62d51f..51e3efe 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverViewModel.kt @@ -18,6 +18,8 @@ import com.lukouguoji.module_base.ktx.launchLoadingCollect 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 dev.utils.common.DateUtils import com.lukouguoji.module_base.ktx.formatDate import kotlinx.coroutines.launch @@ -33,21 +35,67 @@ class IntExpOutHandoverViewModel : BasePageViewModel() { val fdest = MutableLiveData("") // 目的站 val uldNo = MutableLiveData("") // ULD编号 + // ========== 手机版(5.5 寸手持端)专用筛选条件 ========== + // 平板布局不含对应控件,两者保持空值 → 不会进入请求参数,平板查询行为与改造前完全一致 + val handoverState = MutableLiveData("") // 交接状态:"" 全部 / "0" 待交接 / "1" 已交接 + val hoId = MutableLiveData("") // 交接人(仓管编码) + + /** 交接人下拉数据(仅手机版筛选弹层使用,由 [initPhoneExtras] 触发加载) */ + val hoUserList = MutableLiveData>(emptyList()) + + /** 手机版状态 Tab 配置 */ + val handoverStateTabs = MutableLiveData( + listOf(KeyValue("待交接", "0"), KeyValue("已交接", "1")) + ) + + /** 手机版状态 Tab 角标(与 [handoverStateTabs] 等长) */ + val handoverStateCounts = MutableLiveData(listOf("", "")) + + /** + * 是否启用手机版专属数据(Tab 角标计数、交接人下拉)。 + * + * 由 Activity 在手机形态下置 true。平板端保持 false, + * 因此不会产生任何额外接口请求,平板行为零变化。 + */ + private var phoneExtrasEnabled = false + // ========== 统计信息 ========== val totalCount = MutableLiveData("0") // 合计票数 val totalWeight = MutableLiveData("0") // 总重量 // ========== 全选状态 ========== val isAllChecked = MutableLiveData(false) - - fun onItemCheckChanged() { - updateCheckAllStatus() - } - - fun updateCheckAllStatus() { - val list = pageModel.rv?.commonAdapter()?.items as? List ?: return - isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() } - } + + /** 已选数量(手机版底部操作条「已选 N 项」) */ + val selectedCount = MutableLiveData("0") + + /** + * 开启手机版专属数据:默认停留「待交接」Tab、加载交接人下拉、启用 Tab 角标计数。 + * 仅由手机形态的 Activity 调用。 + */ + fun initPhoneExtras() { + phoneExtrasEnabled = true + handoverState.value = "0" + DictUtils.getWHSUserList(addAll = false) { list -> + hoUserList.postValue(list) + } + } + + fun onItemCheckChanged() { + updateCheckAllStatus() + } + + fun updateCheckAllStatus() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() } + updateSelectedCount() + } + + /** 刷新已选数量 */ + private fun updateSelectedCount() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + selectedCount.value = list.count { it.checked.get() }.toString() + } // ========== 适配器配置 ========== val itemViewHolder = IntExpOutHandoverViewHolder::class.java @@ -70,6 +118,7 @@ class IntExpOutHandoverViewModel : BasePageViewModel() { val shouldCheckAll = !isAllChecked.value!! list.forEach { it.checked.set(shouldCheckAll) } isAllChecked.value = shouldCheckAll + updateSelectedCount() pageModel.rv?.commonAdapter()?.notifyDataSetChanged() } @@ -168,7 +217,10 @@ class IntExpOutHandoverViewModel : BasePageViewModel() { "fdate" to flightDate.value?.ifEmpty { null }, "fno" to flightNo.value?.ifEmpty { null }, "fdest" to fdest.value?.ifEmpty { null }, - "uld" to uldNo.value?.ifEmpty { null } + "uld" to uldNo.value?.ifEmpty { null }, + // 以下两项为手机版新增筛选维度,平板端保持空值故不参与查询 + "hoState" to handoverState.value?.ifEmpty { null }, + "hoId" to hoId.value?.ifEmpty { null } ) // 列表参数 (含分页) @@ -193,5 +245,33 @@ class IntExpOutHandoverViewModel : BasePageViewModel() { totalWeight.value = (data?.totalWeight ?: 0.0).toString() } } + + // 手机版 Tab 角标计数(平板端不触发,无额外请求) + if (phoneExtrasEnabled) { + loadTabCounts(filterParams) + } + } + + /** + * 加载「待交接 / 已交接」Tab 角标数量。 + * + * 复用统计接口,分别以 hoState=0 / 1 各查一次,且沿用当前其余筛选条件, + * 保证角标与列表口径一致。仅手机版调用。 + */ + private fun loadTabCounts(filterParams: Map) { + listOf("0", "1").forEachIndexed { index, state -> + val params = (filterParams + mapOf("hoState" to state)).toRequestBody() + launchCollect({ NetApply.api.getIntExpOutHandoverTotal(params) }) { + onSuccess = { result -> + val count = (result.data?.wbNumber ?: 0).toString() + val current = handoverStateCounts.value?.toMutableList() + ?: mutableListOf("", "") + if (index < current.size) { + current[index] = count + handoverStateCounts.value = current + } + } + } + } } } diff --git a/module_gjc/src/main/release/AndroidManifest.xml b/module_gjc/src/main/release/AndroidManifest.xml index 6191e52..ab1dfc6 100644 --- a/module_gjc/src/main/release/AndroidManifest.xml +++ b/module_gjc/src/main/release/AndroidManifest.xml @@ -1,82 +1,82 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_gjc/src/main/res/layout-sw600dp/activity_int_exp_move.xml b/module_gjc/src/main/res/layout-sw600dp/activity_int_exp_move.xml new file mode 100644 index 0000000..2cef614 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/activity_int_exp_move.xml @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/activity_int_exp_out_handover.xml b/module_gjc/src/main/res/layout-sw600dp/activity_int_exp_out_handover.xml new file mode 100644 index 0000000..38541af --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/activity_int_exp_out_handover.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/item_int_exp_move.xml b/module_gjc/src/main/res/layout-sw600dp/item_int_exp_move.xml new file mode 100644 index 0000000..2ecdcdf --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/item_int_exp_move.xml @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/item_int_exp_out_handover.xml b/module_gjc/src/main/res/layout-sw600dp/item_int_exp_out_handover.xml new file mode 100644 index 0000000..de4737a --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/item_int_exp_out_handover.xml @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_int_exp_move.xml b/module_gjc/src/main/res/layout/activity_int_exp_move.xml index 2cef614..27e942d 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_move.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_move.xml @@ -1,206 +1,168 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_int_exp_move_detail.xml b/module_gjc/src/main/res/layout/activity_int_exp_move_detail.xml new file mode 100644 index 0000000..7698a48 --- /dev/null +++ b/module_gjc/src/main/res/layout/activity_int_exp_move_detail.xml @@ -0,0 +1,268 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_int_exp_out_handover.xml b/module_gjc/src/main/res/layout/activity_int_exp_out_handover.xml index a78b0ba..6d781bf 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_out_handover.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_out_handover.xml @@ -1,192 +1,162 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_int_exp_out_handover_detail.xml b/module_gjc/src/main/res/layout/activity_int_exp_out_handover_detail.xml new file mode 100644 index 0000000..bcb110d --- /dev/null +++ b/module_gjc/src/main/res/layout/activity_int_exp_out_handover_detail.xml @@ -0,0 +1,263 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_int_exp_move.xml b/module_gjc/src/main/res/layout/item_int_exp_move.xml index 2ecdcdf..7beda0a 100644 --- a/module_gjc/src/main/res/layout/item_int_exp_move.xml +++ b/module_gjc/src/main/res/layout/item_int_exp_move.xml @@ -1,319 +1,202 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_int_exp_out_handover.xml b/module_gjc/src/main/res/layout/item_int_exp_out_handover.xml index de4737a..37cb6b5 100644 --- a/module_gjc/src/main/res/layout/item_int_exp_out_handover.xml +++ b/module_gjc/src/main/res/layout/item_int_exp_out_handover.xml @@ -1,300 +1,225 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/debug/AndroidManifest.xml b/module_gjj/src/main/debug/AndroidManifest.xml index 35bf7ed..d1931f9 100644 --- a/module_gjj/src/main/debug/AndroidManifest.xml +++ b/module_gjj/src/main/debug/AndroidManifest.xml @@ -1,25 +1,25 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_gjj/src/main/release/AndroidManifest.xml b/module_gjj/src/main/release/AndroidManifest.xml index 64c654b..1556983 100644 --- a/module_gjj/src/main/release/AndroidManifest.xml +++ b/module_gjj/src/main/release/AndroidManifest.xml @@ -1,99 +1,99 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_gnc/src/main/debug/AndroidManifest.xml b/module_gnc/src/main/debug/AndroidManifest.xml index b6f1468..3817219 100644 --- a/module_gnc/src/main/debug/AndroidManifest.xml +++ b/module_gnc/src/main/debug/AndroidManifest.xml @@ -1,25 +1,25 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_gnc/src/main/release/AndroidManifest.xml b/module_gnc/src/main/release/AndroidManifest.xml index 97d68cb..787036a 100644 --- a/module_gnc/src/main/release/AndroidManifest.xml +++ b/module_gnc/src/main/release/AndroidManifest.xml @@ -1,99 +1,99 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_gnj/src/main/AndroidManifest.xml b/module_gnj/src/main/AndroidManifest.xml index 7676f00..3647888 100644 --- a/module_gnj/src/main/AndroidManifest.xml +++ b/module_gnj/src/main/AndroidManifest.xml @@ -1,26 +1,26 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/module_gnj/src/main/debug/AndroidManifest.xml b/module_gnj/src/main/debug/AndroidManifest.xml index 2c3b8a2..59e94b0 100644 --- a/module_gnj/src/main/debug/AndroidManifest.xml +++ b/module_gnj/src/main/debug/AndroidManifest.xml @@ -1,44 +1,44 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_gnj/src/main/release/AndroidManifest.xml b/module_gnj/src/main/release/AndroidManifest.xml index a989e04..90f0d3e 100644 --- a/module_gnj/src/main/release/AndroidManifest.xml +++ b/module_gnj/src/main/release/AndroidManifest.xml @@ -1,86 +1,86 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_hangban/src/main/debug/AndroidManifest.xml b/module_hangban/src/main/debug/AndroidManifest.xml index d4c68cd..2156499 100644 --- a/module_hangban/src/main/debug/AndroidManifest.xml +++ b/module_hangban/src/main/debug/AndroidManifest.xml @@ -1,25 +1,25 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_hangban/src/main/release/AndroidManifest.xml b/module_hangban/src/main/release/AndroidManifest.xml index 268892c..7305989 100644 --- a/module_hangban/src/main/release/AndroidManifest.xml +++ b/module_hangban/src/main/release/AndroidManifest.xml @@ -1,28 +1,28 @@ - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/module_mit/src/main/debug/AndroidManifest.xml b/module_mit/src/main/debug/AndroidManifest.xml index 6bfb851..58f89d9 100644 --- a/module_mit/src/main/debug/AndroidManifest.xml +++ b/module_mit/src/main/debug/AndroidManifest.xml @@ -1,25 +1,25 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_mit/src/main/release/AndroidManifest.xml b/module_mit/src/main/release/AndroidManifest.xml index be048cb..d9c0500 100644 --- a/module_mit/src/main/release/AndroidManifest.xml +++ b/module_mit/src/main/release/AndroidManifest.xml @@ -1,43 +1,43 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ 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 a6b6813..81dcab1 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 @@ -1,48 +1,85 @@ -package com.sixin.module_p.ui.enter.gj - -import com.lukouguoji.module_base.base.BaseViewModel -import com.lukouguoji.module_base.bean.ActionBean -import com.lukouguoji.module_base.common.Constant -import com.lukouguoji.module_base.db.perference.SharedPreferenceUtil -import com.lukouguoji.module_base.ktx.loge -import com.sixin.module_p.R -import com.sixin.module_p.ui.guobang.PdaGuoBangActivity -import com.sixin.module_p.ui.lihuo.PdaLiHuoActivity -import com.sixin.module_p.ui.shouyun.PdaShouYunActivity -import com.sixin.module_p.ui.zuzhuang.PdaZuZhuangActivity -import dev.DevUtils - -class GjViewModel : BaseViewModel() { - - val actionList = listOf( - ActionBean("普货收运", R.drawable.gjc_shou_yun_icon, Constant.AuthName.GjcAppDomExpCheckin), - ActionBean("板箱组装", R.drawable.img_bxzz, Constant.AuthName.GjcBanXListActivity), - ActionBean("板箱过磅", R.drawable.gjc_fu_bang_icon, Constant.AuthName.GjcFuBangActivity), - ActionBean("进港理货", R.drawable.img_jglh, Constant.AuthName.GjjTallyListActivity), - ).filter { SharedPreferenceUtil.getString(Constant.Share.authList).contains(it.key) } - - fun onItemClick(position: Int) { - when (val title = actionList[position].title) { - "普货收运" -> { - PdaShouYunActivity.start(DevUtils.getTopActivity()) - } - - "板箱组装" -> { - PdaZuZhuangActivity.start(DevUtils.getTopActivity()) - } - - "板箱过磅" -> { - PdaGuoBangActivity.start(DevUtils.getTopActivity()) - } - - "进港理货" -> { - PdaLiHuoActivity.start(DevUtils.getTopActivity()) - } - - else -> { - loge("点击事件 $title 未处理") - } - } - } - -} \ No newline at end of file +package com.sixin.module_p.ui.enter.gj + +import com.alibaba.android.arouter.launcher.ARouter +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.ActionBean +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.db.perference.SharedPreferenceUtil +import com.lukouguoji.module_base.ktx.loge +import com.lukouguoji.module_base.router.ARouterConstants +import com.sixin.module_p.R +import com.sixin.module_p.ui.guobang.PdaGuoBangActivity +import com.sixin.module_p.ui.lihuo.PdaLiHuoActivity +import com.sixin.module_p.ui.shouyun.PdaShouYunActivity +import com.sixin.module_p.ui.zuzhuang.PdaZuZhuangActivity +import dev.DevUtils + +/** + * 手持端首页「国际业务」Tab + * + * 菜单项是**手写清单**(不是接口下发),只用登录返回的 authList 做权限过滤: + * 某项没配 [ActionBean.key] 对应的权限串时不显示。所以新页面适配完之后 + * **必须回来这里加一行**,否则手机端首页根本没有入口。 + * + * 两类跳转: + * - 带 [ActionBean.route] → 通用 ARouter 跳转(module_p 不依赖 module_gjc 等业务模块, + * 跨模块只能走路由)。**5.5 寸适配页一律用这种,加一行即可。** + * - 不带 route → 落到 [onItemClick] 的 when 分支(module_p 内部的 PDA 专用页面) + */ +class GjViewModel : BaseViewModel() { + + val actionList = listOf( + // ===== module_p 内的 PDA 专用页面(无 route,走 when 分支) ===== + ActionBean("普货收运", R.drawable.gjc_shou_yun_icon, Constant.AuthName.GjcAppDomExpCheckin), + ActionBean("板箱组装", R.drawable.img_bxzz, Constant.AuthName.GjcBanXListActivity), + ActionBean("板箱过磅", R.drawable.gjc_fu_bang_icon, Constant.AuthName.GjcFuBangActivity), + ActionBean("进港理货", R.drawable.img_jglh, Constant.AuthName.GjjTallyListActivity), + + // ===== 5.5 寸手机版已适配页面(图标复用 Pad 端同款,跳转走 ARouter) ===== + ActionBean( + "出港移库", + R.drawable.gjc_yi_ku_icon, + Constant.AuthName.GjcYiKuListActivity, + ARouterConstants.ACTIVITY_URL_INT_EXP_MOVE + ), + ActionBean( + "出库交接", + R.drawable.img_gjc_chuku_jiaojie, + Constant.AuthName.GjcIntExpOutHandover, + ARouterConstants.ACTIVITY_URL_INT_EXP_OUT_HANDOVER + ), + ).filter { SharedPreferenceUtil.getString(Constant.Share.authList).contains(it.key) } + + fun onItemClick(position: Int) { + val bean = actionList.getOrNull(position) ?: return + + // 配了路由的直接跳(5.5 寸适配页走这条) + if (bean.route.isNotEmpty()) { + ARouter.getInstance().build(bean.route).navigation() + return + } + + when (bean.title) { + "普货收运" -> { + PdaShouYunActivity.start(DevUtils.getTopActivity()) + } + + "板箱组装" -> { + PdaZuZhuangActivity.start(DevUtils.getTopActivity()) + } + + "板箱过磅" -> { + PdaGuoBangActivity.start(DevUtils.getTopActivity()) + } + + "进港理货" -> { + PdaLiHuoActivity.start(DevUtils.getTopActivity()) + } + + else -> { + loge("点击事件 ${bean.title} 未处理") + } + } + } + +} diff --git a/module_p/src/main/res/drawable-xxhdpi/gjc_yi_ku_icon.png b/module_p/src/main/res/drawable-xxhdpi/gjc_yi_ku_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8962030876f328948b40f6c8ecceb91796594049 GIT binary patch literal 32732 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 Date: Wed, 29 Jul 2026 15:13:43 +0800 Subject: [PATCH 02/29] =?UTF-8?q?fix:=20=E5=87=BA=E5=BA=93=E4=BA=A4?= =?UTF-8?q?=E6=8E=A5=E4=BA=A4=E6=8E=A5=E7=8A=B6=E6=80=81=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E5=90=8D=E6=94=B9=E4=B8=BAhandoverState=E5=B9=B6=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E5=86=85=E7=BD=91=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 按 api-doc 接口文档修正交接状态入参 hoState → handoverState(原参数被后端 静默忽略,两个 Tab 返回同一批数据);内网实机验证 0/1 过滤与 App 端到端链路 均生效,平板端回归无影响 - 新增《后端接口对接问题清单.xlsx》:按模块/页面/接口定义/接口地址索引的后端 对接文档,含 5 项待处理缺口(移库缺航班字段/操作人姓名/数据不回填、交接缺 交接人入参、pageQueryTotal 出参恒 0)+ 1 项已验证归档 - phone-adapt skill 新增 references/api-doc.md(api-doc MCP 核对流程 + 内网 直调验证技巧),阶段 2 改为「先查接口文档再问用户」,修正 verification.md 中「后端不认 hoState」的过时误判结论 - CLAUDE.md / CHANGELOG.md 同步走查与验证结论 Co-Authored-By: Claude Fable 5 --- .claude/skills/phone-adapt/SKILL.md | 27 ++++-- .../skills/phone-adapt/references/api-doc.md | 86 ++++++++++++++++++ .../phone-adapt/references/verification.md | 12 ++- CHANGELOG.md | 16 ++++ CLAUDE.md | 10 +- documents/后端接口对接问题清单.xlsx | Bin 0 -> 12337 bytes .../viewModel/IntExpOutHandoverViewModel.kt | 8 +- 7 files changed, 143 insertions(+), 16 deletions(-) create mode 100644 .claude/skills/phone-adapt/references/api-doc.md create mode 100644 documents/后端接口对接问题清单.xlsx diff --git a/.claude/skills/phone-adapt/SKILL.md b/.claude/skills/phone-adapt/SKILL.md index 011853a..4924e42 100644 --- a/.claude/skills/phone-adapt/SKILL.md +++ b/.claude/skills/phone-adapt/SKILL.md @@ -54,12 +54,22 @@ python3 $S/design_shots.py --html "…/出库交接.html" --out /tmp/design \ 把设计稿的每个筛选项/Tab/字段,对照平板 ViewModel 已有的字段: - **已有字段** → 直接复用(如出港移库的 Tab 直接绑既有 `moveState`) -- **平板没有的新维度**(新 Tab 状态、新下拉、新排序)→ **停下来问用户**要用什么接口参数名, - 连带问数据源(如「交接人」用 `DictUtils.getWHSUserList()`) +- **平板没有的新维度**(新 Tab 状态、新下拉、新排序)→ **先查 api-doc MCP 拿权威参数名**, + 流程见 `references/api-doc.md`(连接方式 + 5 个工具 + 逐接口核对清单)。 + 文档里查不到、或业务语义拿不准(如数据源该用哪个 `DictUtils` 方法)才用 `AskUserQuestion` 问用户 -这一步不能猜。出库交接就是实测发现后端 `pageQuery` 根本不认 `hoState`,两个 Tab 返回同一批数据—— -参数名对不对只有后端知道。用 `AskUserQuestion` 一次问清,并在阶段 5 用真实请求体验证是否生效; -**没生效就在交付说明里如实标注**,不要让它看起来是通的。 +这一步不能猜,也**不要拿「实测不生效」当结论**。出库交接第一版猜了 `hoState`,实测两个 Tab +返回同一批数据,一度误判为「后端不支持」;后查 api-doc 才发现正确参数名是 `handoverState`—— +后端对不认识的参数是**静默忽略**,不报错,实测只能证明「这个名字不对」,证不出「后端没这能力」。 + +核对完把结论落两处(模板与格式见 `references/api-doc.md`): + +- 后端真实缺口(缺入参/缺出参/数据不回填)→ 记入 `documents/后端接口对接问题清单.xlsx`, + 这是与后端对接的正式文档,按「模块 → 页面 → 接口定义 → 接口地址」索引,**每个页面适配完都要维护** +- 参数名/字段绑定错误这类前端问题 → 直接改代码 + +阶段 5 仍要用真实请求体验证新参数确实生效;没生效就在清单文档与交付说明里如实标注, +不要让它看起来是通的。 ### 开工前对齐方案 @@ -121,7 +131,7 @@ visibility 即可(Bean 上加个只读计算属性如 `isHandovered` 让 XML val handoverState = MutableLiveData("") // 平板布局无对应控件 → 恒为空 → 不进请求 val filterParams = mapOf( /* 原有字段… */ - "hoState" to handoverState.value?.ifEmpty { null }, + "handoverState" to handoverState.value?.ifEmpty { null }, // 参数名以 api-doc 为准 ) // 手机专属的额外请求(Tab 角标计数、新下拉字典)用内部开关控制 @@ -252,11 +262,13 @@ binding.rv.postDelayed({ ## 收尾:文档与交付说明 -代码之外还要落三处文档,否则下一个人会重复踩坑: +代码之外还要落四处文档,否则下一个人会重复踩坑: - 新增了公共组件/资源 → 更新 `CLAUDE.md`「手机版公共组件库」表 + `references/components.md` - 踩到新坑(崩溃、静默失效、环境问题)→ 写进 `CLAUDE.md`「常见编译错误速查」和本 skill 的 对应 reference,把**定位手法**也写上,不只写结论 +- 接口有后端缺口(阶段 2 / 阶段 5 发现的)→ 维护 `documents/后端接口对接问题清单.xlsx`; + 已确认的字段语义追加到 `references/api-doc.md` 的「已核对过的语义」,别让下个页面再查一遍 - `CHANGELOG.md` 追加条目(新增 / 改进 / 修复 / 验证 四段),记忆文件 `phone-5.5inch-adaptation.md` 同步 @@ -270,6 +282,7 @@ binding.rv.postDelayed({ ## 参考文件 +- `references/api-doc.md` — api-doc MCP 连接与逐接口核对流程、后端缺口记录规范、已核对字段语义(阶段 2 前读) - `references/components.md` — 7 个手机版公共组件的属性表、用法与封装新组件的规矩(写布局前读) - `references/pad-safety.md` — 布局变体约束、Pad 零破坏模式、易崩点(写代码前读) - `references/verification.md` — 双端 adb 命令、登录与直启、已知环境坑(验证前读) diff --git a/.claude/skills/phone-adapt/references/api-doc.md b/.claude/skills/phone-adapt/references/api-doc.md new file mode 100644 index 0000000..6368bc0 --- /dev/null +++ b/.claude/skills/phone-adapt/references/api-doc.md @@ -0,0 +1,86 @@ +# api-doc MCP:接口定义核对流程(阶段 2 必读) + +适配页面前,**所有用到的接口都要在 api-doc(AgentFox)里核对一遍入参/出参**, +不要靠平板代码或猜测推断参数名——出库交接就因为猜了 `hoState`(实际是 `handoverState`) +白白折腾了一轮实机排查。 + +## 连接方式 + +项目 `.mcp.json` 已配置 `api-doc` 远程 HTTP MCP。若会话内 MCP 工具可直接调用 +(`mcp__api-doc__*`),直接用;**若工具没有注入会话**(ToolSearch 搜不到),用 curl 走 +MCP 协议手工调用,三步: + +```bash +URL=$(python3 -c "import json;print(json.load(open('.mcp.json'))['mcpServers']['api-doc']['url'])") +AUTH="Authorization: $(python3 -c "import json;print(json.load(open('.mcp.json'))['mcpServers']['api-doc']['headers']['Authorization'])")" + +# 1) initialize:从响应头 mcp-session-id 取会话 id +curl -s -D /tmp/mcp_headers.txt -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \ + -H "Accept: application/json, text/event-stream" \ + -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"claude-code","version":"1.0"}}}' > /dev/null +SID=$(grep -i 'mcp-session-id' /tmp/mcp_headers.txt | tr -d '\r' | awk '{print $2}') + +# 2) initialized 通知(必须发,否则 tools/* 报 session 未初始化) +curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \ + -H "Accept: application/json, text/event-stream" -H "mcp-session-id: $SID" \ + -d '{"jsonrpc":"2.0","method":"notifications/initialized"}' > /dev/null + +# 3) tools/call(响应是 SSE,`sed 's/^data: //'` 后按 JSON 解析) +curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \ + -H "Accept: application/json, text/event-stream" -H "mcp-session-id: $SID" \ + -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_endpoints","arguments":{"keyword":"IntExpMove"}}}' +``` + +## 可用工具(5 个) + +| 工具 | 用途 | +|------|------| +| `get_project_overview` | 项目概览 + 模块清单(首次调用) | +| `list_modules` | 全部模块含描述 | +| `list_endpoints` | 单模块内接口列表(分页,`moduleId` + `cursor`) | +| `search_endpoints` | 按关键字搜接口(`keyword` 用控制器前缀最准,如 `IntExpOutHandover`) | +| `get_endpoint_detail` | **核心**:单接口完整契约,schema 已拍平成字段表(`endpointId`) | + +## 核对清单(每个页面做一遍) + +对 ViewModel 里每个 `NetApply.api.xxx` 调用: + +1. 从 `module_base/.../http/net/Api.kt` 拿到 `@POST` 路径 → `search_endpoints` 找到接口 → `get_endpoint_detail` +2. **入参**:前端传的每个 key 必须能在文档字段表里找到**同名字段**;找不到 = 传了也白传(后端静默忽略,不报错) +3. **类型**:状态类字段(`moveState`/`handoverState`/`outState`)文档均为 integer,前端传 `"0"` 字符串靠 + Jackson 隐式转换(实测可用);新代码尽量传数字 +4. **出参**:设计稿卡片/详情页的每个展示字段,都要能对上出参字段;对不上就是后端缺口 +5. **结论落两处**: + - 后端缺口(缺入参/缺出参/数据不回填)→ 记入 `documents/后端接口对接问题清单.xlsx` + (按「模块 → 页面 → 接口定义 → 接口地址」格式,含前端现状与期望,状态标 ⏳/🔍) + - 前端可自行解决的(参数名写错、字段绑错)→ 直接改代码,别记成后端问题 + +## 已核对过的语义(别再猜) + +- `IntExpOutHandover`:交接状态入参 = `handoverState`(不是 `hoState`),**2026-07-29 内网实测过滤生效** + (传 0/1 分别返回纯净的待/已交接集合,字符串 `"0"`/`"1"` 同样被接受);`ldId` 是**组装人**不是交接人; + 交接人姓名出参 `hoUserName`,编码 `hoId`;查询入参**没有**交接人筛选(后端缺口 #4) +- `IntExpOutHandover/pageQueryTotal`:**出参恒 0**(任何条件下 totalPc/totalWeight/wbNumber 均为 0, + 与同条件 pageQuery 不一致,后端缺口 #6)——依赖它的 Tab 角标/底部统计显示 0 不是前端问题 +- `IntExpMove`:出参无航班字段(缺口 #1)、无操作人姓名(缺口 #2);`opId`/`opdate`/`businessType` + 文档有定义但实测恒 null(缺口 #3);`pageQueryTotal` 正常(与 pageQuery 口径一致,`moveState` 过滤生效) +- `typeCode/getSpecialCodeByParam`:`flag=1` 国际,`ieFlag` 必须传空串(传 `"E"` 返回空数组) + +## 内网直调验证技巧(比驱动 UI 快得多) + +登录态 token 存在 SharedPreference 里,取出后可以直接 curl 后端做行为验证 +(**注意:不要把 token 打印到输出里**,落临时文件引用): + +```bash +adb -s shell "run-as com.lukouguoji.aerologic cat \ + /data/data/com.lukouguoji.aerologic/shared_prefs/data.xml" \ + | grep -o '[^<]*' | sed 's/.*>//' > /tmp/air_token + +curl -s -X POST "http://192.168.1.250:8093/IntExpOutHandover/pageQuery" \ + -H "Authorization: $(cat /tmp/air_token)" -H "Content-Type: application/json" \ + -d '{"pageNum":1,"pageSize":50,"handoverState":0}' +``` + +用它做「参数是否生效」的 A/B 对比(同条件只改一个参数看 total 变化), +再回 App UI 走一遍确认端到端链路。UI 里的滚轮日期选择器可用 +`input swipe`(慢速 500ms、每次 3 格 ≈ 396px)驱动,滑完截图校准。 diff --git a/.claude/skills/phone-adapt/references/verification.md b/.claude/skills/phone-adapt/references/verification.md index 0499784..4bd91bf 100644 --- a/.claude/skills/phone-adapt/references/verification.md +++ b/.claude/skills/phone-adapt/references/verification.md @@ -101,11 +101,14 @@ $P texts | grep -c "全选" # 用文字变化确认点击确实生效 $P req pageQuery ``` -OkHttp 日志是多行 pretty JSON。看到请求体里有你的字段(如 `"hoState": "0"`)只说明客户端对了。 +OkHttp 日志是多行 pretty JSON。看到请求体里有你的字段(如 `"handoverState": "0"`)只说明客户端对了。 **服务端是否生效要用行为验证**:切到另一个 Tab,看返回数据是否真的变了。 -本次实测:请求正确携带 `hoState:"0"/"1"`,但两个 Tab 返回同一批数据 → 后端没做过滤。 -这种情况**必须在交付说明里如实标注**,不能让它看起来是通的。 +⚠️ 行为验证失败时**先怀疑参数名,再怀疑后端**:出库交接第一版传 `hoState`,两个 Tab 返回同一批数据, +一度误判为「后端没做过滤」;实际是参数名错了(api-doc 里是 `handoverState`),后端对不认识的参数 +**静默忽略**。正确顺序:查 `references/api-doc.md` 核对参数名 → 用 token 直调后端做 A/B 对比 +(同条件只改一个参数看 total 变化)→ 仍不生效才定性为后端缺陷并记入 +`documents/后端接口对接问题清单.xlsx`。 ## 无数据时怎么核对 UI @@ -136,7 +139,8 @@ for i in $(seq 1 10); do adb -s shell dumpsys window | grep -m1 -oE "mRo ``` 平板则应首屏就是横屏(截图宽 > 高)。若手机出现横屏帧,检查该 Activity 的 Manifest -是否漏写 `android:screenOrientation="@integer/screen_orientation"`。 +是否写成了别的值——**必须是 `android:screenOrientation="unspecified"`**(写死 `userLandscape` +或用 `@integer/...` 资源引用都会出问题,详见 SKILL.md 阶段 4)。 ## Pad 端回归(必做) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fb81c4..1370eca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,22 @@ 格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/), 版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。 +## [Unreleased] + +### 修复 (Fixed) +- 出库交接手机版「待/已交接」Tab 与角标计数的过滤参数名修正:`hoState` → `handoverState` + (以 api-doc 接口文档为准;此前误传 `hoState` 被后端静默忽略,两个 Tab 返回同一批数据)。 + 2026-07-29 内网实机验证通过:fdate=2026-07-16 下待交接/已交接 Tab 分别精确返回对应板箱,与后端直调结果一致。 + 验证中发现 `IntExpOutHandover/pageQueryTotal` 出参恒 0(后端缺陷,致 Tab 角标与平板底部统计为 0,已记录问题清单 #6) + +### 新增 (Added) +- 新增《后端接口对接问题清单》(`documents/后端接口对接问题清单.xlsx`):手机端适配走查发现的接口缺口 + (移库列表缺航班字段、缺操作人姓名、`opId/opdate/businessType` 不回填、出库交接查询缺「交接人」入参), + 按模块/页面/接口定义/接口地址索引,作为与后端对接的持续维护文档 +- phone-adapt skill 新增 `references/api-doc.md`:api-doc MCP 连接与逐接口核对流程,接口对齐从「问用户」升级为「先查接口文档」 + +--- + ## [1.9.0] - 2026-07-29 ### 新增 (Added) diff --git a/CLAUDE.md b/CLAUDE.md index fe62cfb..29d5377 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1089,12 +1089,18 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = - ✅ **已完成**:适配框架 + 手机端公共资源 + 7 个手机版公共组件 - ✅ **已完成页面**: - - 「国际出港移库」`IntExpMoveActivity`(框架参考页,筛选弹层内暂仍用 `PadSearchLayout`) + - 「国际出港移库」`IntExpMoveActivity` + 「运单详情」`IntExpMoveDetailActivity`(框架参考页) - 「国际出港出库交接」`IntExpOutHandoverActivity` + 「板箱详情」`IntExpOutHandoverDetailActivity` (公共组件首个完整落地页,双端实机验证通过) - ⏳ **待办**: - - 把「移库」页筛选弹层内的 `PadSearchLayout` 换成 `PhoneDataLayout`,视觉统一 - `PhoneSearchBar` 接入 AutoQuery 联想(`AutoQueryManager` 目前只对接了 Pad 系组件) + - 出库交接 Tab 角标恒 0:`IntExpOutHandover/pageQueryTotal` 出参恒 0(后端缺陷,问题清单 #6), + 后端修复后角标自动恢复(`handoverState` 过滤本身已于 2026-07-29 实机验证通过)生效 +- 📋 **接口对接**:适配中发现的后端接口缺口统一记录在 `documents/后端接口对接问题清单.xlsx` + (按模块/页面/接口定义/接口地址索引,与后端对接的正式文档,每页适配完必须维护); + 接口入参/出参一律以 api-doc MCP 为准核对,流程见 + `.claude/skills/phone-adapt/references/api-doc.md`——**后端对不认识的参数静默忽略**, + 猜参数名会得出「后端不支持」的误判(出库交接 `hoState`→`handoverState` 已踩过) ### 调试便利:直接拉起页面 diff --git a/documents/后端接口对接问题清单.xlsx b/documents/后端接口对接问题清单.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..520c677906eb1eaf66f7bd8bac1153d9bb8a0f09 GIT binary patch literal 12337 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 literal 0 HcmV?d00001 diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverViewModel.kt index 51e3efe..40e57ba 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverViewModel.kt @@ -219,7 +219,9 @@ class IntExpOutHandoverViewModel : BasePageViewModel() { "fdest" to fdest.value?.ifEmpty { null }, "uld" to uldNo.value?.ifEmpty { null }, // 以下两项为手机版新增筛选维度,平板端保持空值故不参与查询 - "hoState" to handoverState.value?.ifEmpty { null }, + // 参数名以 api-doc 为准:交接状态为 handoverState(integer,0 未交接 / 1 已交接)。 + // hoId(交接人)后端查询入参暂不支持,已记录到 documents/后端接口对接问题清单.xlsx + "handoverState" to handoverState.value?.ifEmpty { null }, "hoId" to hoId.value?.ifEmpty { null } ) @@ -255,12 +257,12 @@ class IntExpOutHandoverViewModel : BasePageViewModel() { /** * 加载「待交接 / 已交接」Tab 角标数量。 * - * 复用统计接口,分别以 hoState=0 / 1 各查一次,且沿用当前其余筛选条件, + * 复用统计接口,分别以 handoverState=0 / 1 各查一次,且沿用当前其余筛选条件, * 保证角标与列表口径一致。仅手机版调用。 */ private fun loadTabCounts(filterParams: Map) { listOf("0", "1").forEachIndexed { index, state -> - val params = (filterParams + mapOf("hoState" to state)).toRequestBody() + val params = (filterParams + mapOf("handoverState" to state)).toRequestBody() launchCollect({ NetApply.api.getIntExpOutHandoverTotal(params) }) { onSuccess = { result -> val count = (result.data?.wbNumber ?: 0).toString() From 5a019a55c4bfdbbbd043a776441efe569d819c19 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Wed, 29 Jul 2026 16:30:42 +0800 Subject: [PATCH 03/29] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90ULD=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E9=A1=B5=E9=9D=A25.5=E5=AF=B8=E6=89=8B=E6=9C=BA?= =?UTF-8?q?=E7=AB=AF=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) { From 1eb288a70355f4db047133fadb8b9cd075446de4 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Wed, 29 Jul 2026 20:09:55 +0800 Subject: [PATCH 04/29] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=87=BA?= =?UTF-8?q?=E6=B8=AF=E8=AE=A1=E9=87=8D=E9=A1=B5=E9=9D=A25.5=E5=AF=B8?= =?UTF-8?q?=E6=89=8B=E6=9C=BA=E7=AB=AF=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 待计重列表:三格统计、卡片单票提前运抵、筛选弹层(通道号/承运人/运单类型/代理人) - 开始计重:预配统计卡 + PhoneFormRow 表单 - 计重记录:三格统计、筛选弹层(入库日期/代理人/特码/目的站/计重人) - 计重明细:新增手机端全屏「修改记录」覆层,复用平板编辑链路 - 新增手机专属「运单详情」页 - 手机首页「国际」Tab 增加「出港计重」入口 - 登记后端接口缺口 7 项(#12~#18)至问题清单 Co-Authored-By: Claude Opus 4.6 --- .../skills/phone-adapt/references/api-doc.md | 8 + .../phone-adapt/references/components.md | 6 +- CHANGELOG.md | 22 + CLAUDE.md | 8 + app/src/debug/AndroidManifest.xml | 30 + app/src/main/AndroidManifest.xml | 6 + documents/后端接口对接问题清单.xlsx | Bin 14095 -> 16942 bytes .../module_base/bean/GjcCheckInRecord.kt | 12 + .../lukouguoji/module_base/bean/GjcMaWb.kt | 2 + .../main/res/drawable/bg_phone_btn_weak.xml | 7 + .../res/drawable/bg_phone_card_top_accent.xml | 9 + .../main/res/drawable/ic_phone_clipboard.xml | 11 + .../src/main/res/drawable/ic_phone_weight.xml | 11 + .../gjc/activity/GjcWeighingListActivity.kt | 43 + .../GjcWeighingRecordDetailsActivity.kt | 22 + .../activity/GjcWeighingRecordListActivity.kt | 39 + .../gjc/activity/GjcWeighingStartActivity.kt | 101 ++- .../activity/GjcWeighingWbDetailActivity.kt | 40 + .../gjc/holder/GjcCheckInRecordViewHolder.kt | 5 + .../gjc/holder/GjcWeighingRecordViewHolder.kt | 19 +- .../gjc/holder/GjcWeighingViewHolder.kt | 18 +- .../GjcWeighingRecordDetailsViewModel.kt | 38 + .../viewModel/GjcWeighingRecordViewModel.kt | 67 +- .../viewModel/GjcWeighingStartViewModel.kt | 28 +- .../gjc/viewModel/GjcWeighingViewModel.kt | 147 +++- .../viewModel/GjcWeighingWbDetailViewModel.kt | 30 + .../activity_gjc_weighing_list.xml | 227 +++++ .../activity_gjc_weighing_record_details.xml | 279 +++++++ .../activity_gjc_weighing_record_list.xml | 188 +++++ .../activity_gjc_weighing_start.xml | 496 +++++++++++ .../item_gjc_check_in_record.xml | 95 +++ .../res/layout-sw600dp/item_gjc_weighing.xml | 316 +++++++ .../item_gjc_weighing_record.xml | 272 ++++++ .../res/layout/activity_gjc_weighing_list.xml | 523 +++++++----- .../activity_gjc_weighing_record_details.xml | 527 ++++++------ .../activity_gjc_weighing_record_list.xml | 484 +++++++---- .../layout/activity_gjc_weighing_start.xml | 782 +++++++----------- .../activity_gjc_weighing_wb_detail.xml | 254 ++++++ .../res/layout/item_gjc_check_in_record.xml | 291 ++++--- .../src/main/res/layout/item_gjc_weighing.xml | 457 ++++------ .../res/layout/item_gjc_weighing_record.xml | 395 +++------ .../sixin/module_p/ui/enter/gj/GjViewModel.kt | 6 + .../img_gjc_chugangjizhong.png | Bin 0 -> 31892 bytes 43 files changed, 4380 insertions(+), 1941 deletions(-) create mode 100644 module_base/src/main/res/drawable/bg_phone_btn_weak.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_card_top_accent.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_clipboard.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_weight.xml create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingWbDetailActivity.kt create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingWbDetailViewModel.kt create mode 100644 module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_list.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_record_details.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_record_list.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_start.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/item_gjc_check_in_record.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/item_gjc_weighing.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/item_gjc_weighing_record.xml create mode 100644 module_gjc/src/main/res/layout/activity_gjc_weighing_wb_detail.xml create mode 100644 module_p/src/main/res/drawable-xxhdpi/img_gjc_chugangjizhong.png diff --git a/.claude/skills/phone-adapt/references/api-doc.md b/.claude/skills/phone-adapt/references/api-doc.md index b7358d6..8634cee 100644 --- a/.claude/skills/phone-adapt/references/api-doc.md +++ b/.claude/skills/phone-adapt/references/api-doc.md @@ -70,6 +70,14 @@ curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \ 0 正常/1 故障(三态需求=缺口 #7);无「来源」字段(#8)、无 `checkInDate`/`ifNo` 筛选入参(#9)、 无批量删除(#10,`deleteUld` 是 `@Query` 单条);出参 `ifNo`/`efNo`/`checkInDate`/`checkOutDate` 文档无描述,按命名推断进/出港航班号与出入库时间(#11 待确认) +- `IntExpCheckIn`(出港计重,2026-07-29 内网实测):`likeNo` **并非任意模糊**——按 8 位 `no` + 匹配(11 位 wbNo 或部分号均 0 条),11 位全号必须走 `wbNo`;`checkIn`/`checkInList` + 文档有定义但 `pageQuery`/`pageQueryTotal` **均静默忽略**(缺口 #12,待计重/计重中计数依赖); + 查询入参无通道号/承运人/运单类型(#13)、`checked/*` 无收运时间范围(#14);`checked/pageQuery` + 出参无通道号(#15)但有 `userName`(计重人中文名);`listRecordByWh` 出参计重人仅 `opId`(#16); + `preArrive` 成功后 `pageQuery` 的 `arriveFlag` 不回填(#17);`splitCheckIn`/`completeCheckIn` + 无 `palletNumber`/`carWeight` 入参(#18,手机版托盘数量/自重按设计稿传预留参数); + 运单类型字典:`DictUtils.getWaybillTypeList2(ieFlag="E", type="IO")` ## 内网直调验证技巧(比驱动 UI 快得多) diff --git a/.claude/skills/phone-adapt/references/components.md b/.claude/skills/phone-adapt/references/components.md index 5d9bc39..bc747d4 100644 --- a/.claude/skills/phone-adapt/references/components.md +++ b/.claude/skills/phone-adapt/references/components.md @@ -122,11 +122,13 @@ android.util.Log.d("DBG", "value '$field' -> '$v'", Throwable("trace")) `phone_divider` `phone_badge_bg` `phone_green` `phone_check_border` `phone_tag_gray_*` `phone_tag_green_*` `phone_tag_red_*` `phone_orange_bg/text` - 背景:`bg_phone_card` `bg_phone_search` `bg_phone_input` `bg_phone_stat_box` `bg_phone_panel_top` - `bg_phone_icon_round` `bg_phone_btn_primary` `bg_phone_btn_outline` `bg_phone_badge` - `bg_phone_tag_green/gray/red/orange` `bg_phone_card_header_blue/green` + `bg_phone_icon_round` `bg_phone_btn_primary` `bg_phone_btn_outline` `bg_phone_btn_weak`(浅蓝弱按钮) + `bg_phone_badge` `bg_phone_tag_green/gray/red/orange` `bg_phone_card_header_blue/green` + `bg_phone_card_top_accent`(卡片顶部主色描边条,出港计重头部卡片) - 图标:`ic_phone_airplane` `ic_phone_location` `ic_phone_person` `ic_phone_check_circle` `ic_phone_chevron_right/down` `ic_phone_calendar` `ic_phone_close` `ic_phone_check_round_checked/unchecked`(圆形复选框) + `ic_phone_clipboard`(剪贴板,白色 FAB 用)`ic_phone_weight`(砝码,可 tint) - 复用 Pad 的矢量图:`img_search` `img_scan` `img_filter`(可 `app:tint` 染色) 设计稿里的 MDI 图标若缺失,直接写 24×24 的 vector(用 MDI 官方 path),比找位图靠谱且能染色。 diff --git a/CHANGELOG.md b/CHANGELOG.md index d23c007..c2753ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,28 @@ ## [Unreleased] ### 新增 (Added) +- 「出港计重」5.5 寸手机端适配(首个全链路 4+1 页模块,设计稿 03_出港计重): + 待计重列表(三格统计 总票数/待计重/计重中 + 卡片状态标签 未计重/计重中 + 卡片内单票「提前运抵」+ + FAB 进计重记录 + 筛选弹层 通道号/承运人/运单类型/代理人)、开始计重(头部预配统计卡 + PhoneFormRow 表单, + 托盘数量/托盘自重按设计稿手输)、计重记录(三格统计 + 卡片地磅图标进明细/「查看详情」进运单详情 + + 筛选弹层 入库日期起止/代理人/特码/目的站/计重人)、计重明细(汇总卡含托盘总重 + 记录卡「修改」→ + 全屏「修改记录」覆层,复用平板 isEditMode 编辑链路,保存后留在本页)、手机专属新页「运单详情」 + `GjcWeighingWbDetailActivity`(12 字段只读网格);手机首页「国际」Tab 增「出港计重」入口 +- 新增手机版公共资源:`bg_phone_btn_weak`(浅蓝弱按钮)、`bg_phone_card_top_accent`(卡片顶部主色描边条)、 + `ic_phone_clipboard`、`ic_phone_weight` +- `GjcMaWb` 预留 `palletNumber`/`carWeight` 字段、`GjcCheckInRecord` 增 `carWeightStr` 双向绑定属性 + (均为手机版专属,平板请求体零变化);后端缺口 7 项登记问题清单 #12~#18 + (checkIn 过滤不生效、主列表筛选三入参、入库日期范围、通道号出参、计重人姓名、arriveFlag 不回填、 + 托盘数量/自重入参) + +### 修复 (Fixed) +- 出港计重手机版搜索分流按实测修正:`likeNo` 并非任意模糊(按 8 位 no 匹配), + 11 位全号改走 `wbNo` 精确查询,含字母走 `fno` + +### 验证 (Verified) +- 出港计重双端实机验证通过:手机端 待计重列表/筛选/开始计重(必填校验)/计重记录/记录筛选/运单详情/ + 计重明细/修改覆层保存/单票提前运抵 全链路 crash=0、方向无闪屏、请求体新参数全部正确携带; + 平板端 待计重/计重记录/开始计重 三页回归无变化(横屏、5 搜索条、日期默认今天、地磅区/托盘车号/浮动按钮组均在) - 「ULD管理」5.5 寸手机端适配(app 模块首个适配页):列表卡片(三色状态标签)+ 筛选弹层(入库时间/进港航班号/所属航司/来源)+ 右下角浮动新增 + 底部全选/批量删除(循环调用单条删除接口)+ 一套 `activity_uld_edit` 手机布局覆盖 新增/修改/详情 三态 (详情态右上铅笔进入修改、状态底部选择面板、所在港默认 HFE、必填校验仅手机生效) diff --git a/CLAUDE.md b/CLAUDE.md index fa2bfc2..9be348d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1054,6 +1054,8 @@ DataBinding 适配器统一放在 `PhoneWidgetKtx.kt`(同名属性按控件类 `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`。 +出港计重追加:`bg_phone_btn_weak`(浅蓝弱按钮,卡片内提前运抵)、`bg_phone_card_top_accent` +(卡片顶部主色描边条)、`ic_phone_clipboard`(FAB 剪贴板)、`ic_phone_weight`(砝码图标,可 tint)。 ⚠️ **弹层与浮动按钮的层级**:`PhoneFilterPanel` 默认无 elevation,页面里有带 elevation 的浮动按钮(FAB)时 会穿透到弹层之上——给弹层实例加 `android:elevation="8dp"`(大于 FAB 的 6dp)。 @@ -1102,6 +1104,12 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = (公共组件首个完整落地页,双端实机验证通过) - 「ULD管理」`UldListActivity` + `UldEditActivity`(app 模块首个适配页;一套编辑布局覆盖 新增/修改/详情三态;批量删除为前端循环调用单条接口;状态三态/来源等 5 项后端缺口见问题清单 #7~#11) + - 「出港计重」全链路 4+1 页:`GjcWeighingListActivity`(待计重列表,三格统计 + 卡片单票提前运抵 + + FAB 进记录)、`GjcWeighingStartActivity`(开始计重,托盘数量/自重按设计稿手输)、 + `GjcWeighingRecordListActivity`(计重记录)、`GjcWeighingRecordDetailsActivity`(计重明细, + isEditMode 复用为手机全屏「修改记录」覆层)+ 手机专属新页 `GjcWeighingWbDetailActivity`(运单详情)。 + 搜索分流规则(实测):含字母→fno、11 位数字→wbNo、其余→likeNo(likeNo 按 8 位 no 匹配并非模糊); + checkIn 过滤等 7 项后端缺口见问题清单 #12~#18 - ⏳ **待办**: - `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 0ecb42d..3fabae5 100644 --- a/app/src/debug/AndroidManifest.xml +++ b/app/src/debug/AndroidManifest.xml @@ -50,5 +50,35 @@ android:exported="true" tools:replace="android:exported" /> + + + + + + + + + + + + + + + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e0d5ebd..cc1e1d7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -205,6 +205,12 @@ android:configChanges="orientation|keyboardHidden" android:exported="false" android:screenOrientation="unspecified" /> + + +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 delta 7948 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 + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_card_top_accent.xml b/module_base/src/main/res/drawable/bg_phone_card_top_accent.xml new file mode 100644 index 0000000..b551906 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_card_top_accent.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_clipboard.xml b/module_base/src/main/res/drawable/ic_phone_clipboard.xml new file mode 100644 index 0000000..980d0ed --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_clipboard.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_weight.xml b/module_base/src/main/res/drawable/ic_phone_weight.xml new file mode 100644 index 0000000..ebec08a --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_weight.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt index a0e37bb..f657b23 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt @@ -3,19 +3,26 @@ package com.lukouguoji.gjc.activity import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.databinding.ObservableBoolean import com.alibaba.android.arouter.facade.annotation.Route import com.lukouguoji.gjc.R import com.lukouguoji.gjc.databinding.ActivityGjcWeighingListBinding import com.lukouguoji.gjc.viewModel.GjcWeighingViewModel import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.GjcWeighingBean import com.lukouguoji.module_base.common.ConstantEvent import com.lukouguoji.module_base.impl.FlowBus import com.lukouguoji.module_base.impl.observe import com.lukouguoji.module_base.ktx.getLifecycleOwner import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil /** * 国际出港计重列表页 + * + * 布局 id 不区分设备,平板/手机由资源限定符自动选择: + * layout-sw600dp/activity_gjc_weighing_list.xml(平板) + * layout/activity_gjc_weighing_list.xml(手机) */ @Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_LIST) class GjcWeighingListActivity : @@ -25,10 +32,20 @@ class GjcWeighingListActivity : override fun viewModelClass() = GjcWeighingViewModel::class.java + /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ + val filterPanelVisible = ObservableBoolean(false) + override fun initOnCreate(savedInstanceState: Bundle?) { setBackArrow("国际出港待计重") binding.viewModel = viewModel + binding.activity = this + + // 手机版专属数据:放开默认日期、加载筛选弹层字典、启用三格统计 + // 平板端不调用,查询链路与请求次数与改造前完全一致 + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } // 初始化代理人列表(从API获取) viewModel.initAgentList() @@ -52,6 +69,32 @@ class GjcWeighingListActivity : viewModel.refresh() } + // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 字段) ==================== + + /** 手机版筛选弹层显隐切换 */ + fun toggleFilterPanel() { + filterPanelVisible.set(!filterPanelVisible.get()) + } + + /** 手机版筛选:重置(只清弹层内条件,不影响顶部搜索框) */ + fun resetFilter() { + viewModel.channelFilter.value = "" + viewModel.carrierFilter.value = "" + viewModel.awbTypeFilter.value = "" + viewModel.agentCode.value = "" + } + + /** 手机版筛选:确认 */ + fun confirmFilter() { + filterPanelVisible.set(false) + viewModel.searchClick() + } + + /** 手机版卡片内「提前运抵」(单票,由 ViewHolder 调用) */ + fun preArriveClick(bean: GjcWeighingBean) { + viewModel.arrivedAheadSingle(bean) + } + companion object { @JvmStatic fun start(context: Context) { diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordDetailsActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordDetailsActivity.kt index b9ace48..f2c6887 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordDetailsActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordDetailsActivity.kt @@ -12,12 +12,17 @@ import com.lukouguoji.gjc.holder.GjcCheckInRecordViewHolder import com.lukouguoji.gjc.viewModel.GjcWeighingRecordDetailsViewModel import com.lukouguoji.module_base.base.BaseBindingActivity import com.lukouguoji.module_base.base.CommonAdapter +import com.lukouguoji.module_base.bean.GjcCheckInRecord import com.lukouguoji.module_base.bean.GjcWeighingRecordBean import com.lukouguoji.module_base.common.Constant import com.lukouguoji.module_base.router.ARouterConstants /** * 国际出港计重明细页 + * + * 布局 id 不区分设备,平板/手机由资源限定符自动选择: + * layout-sw600dp/activity_gjc_weighing_record_details.xml(平板,列表内联编辑) + * layout/activity_gjc_weighing_record_details.xml(手机,单条记录经全屏「修改记录」覆层编辑) */ @Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_DETAILS) class GjcWeighingRecordDetailsActivity : @@ -70,6 +75,23 @@ class GjcWeighingRecordDetailsActivity : viewModel.initOnCreated(intent) } + // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 编辑链路) ==================== + + /** + * 手机版:打开「修改记录」覆层编辑指定记录。 + * 复用 [GjcWeighingRecordDetailsViewModel.onModifyClick] 的备份/编辑态逻辑, + * 覆层显隐由 isEditMode 驱动(平板端该状态驱动列表内联编辑,互不影响)。 + */ + fun openPhoneEdit(record: GjcCheckInRecord) { + viewModel.onModifyClick() + binding.editRecord = record + } + + /** 手机版:取消编辑(恢复备份并收起覆层) */ + fun closePhoneEdit() { + viewModel.onCancelClick() + } + companion object { @JvmStatic fun start(context: Context, bean: GjcWeighingRecordBean) { diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt index 5d6253e..bb83248 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt @@ -3,6 +3,7 @@ package com.lukouguoji.gjc.activity import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.databinding.ObservableBoolean import com.alibaba.android.arouter.facade.annotation.Route import com.lukouguoji.gjc.R import com.lukouguoji.gjc.databinding.ActivityGjcWeighingRecordListBinding @@ -13,9 +14,14 @@ import com.lukouguoji.module_base.impl.FlowBus import com.lukouguoji.module_base.impl.observe import com.lukouguoji.module_base.ktx.getLifecycleOwner import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil /** * 国际出港计重记录列表页 + * + * 布局 id 不区分设备,平板/手机由资源限定符自动选择: + * layout-sw600dp/activity_gjc_weighing_record_list.xml(平板) + * layout/activity_gjc_weighing_record_list.xml(手机) */ @Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_LIST) class GjcWeighingRecordListActivity : @@ -25,10 +31,20 @@ class GjcWeighingRecordListActivity : override fun viewModelClass() = GjcWeighingRecordViewModel::class.java + /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ + val filterPanelVisible = ObservableBoolean(false) + override fun initOnCreate(savedInstanceState: Bundle?) { setBackArrow("国际出港计重记录") binding.viewModel = viewModel + binding.activity = this + + // 手机版专属数据:放开默认日期、加载计重人下拉 + // 平板端不调用,查询链路与请求次数与改造前完全一致 + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } // 初始化代理人列表 viewModel.initAgentList() @@ -50,6 +66,29 @@ class GjcWeighingRecordListActivity : viewModel.refresh() } + // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 字段) ==================== + + /** 手机版筛选弹层显隐切换 */ + fun toggleFilterPanel() { + filterPanelVisible.set(!filterPanelVisible.get()) + } + + /** 手机版筛选:重置(只清弹层内条件,不影响顶部搜索框) */ + fun resetFilter() { + viewModel.checkInDateStart.value = "" + viewModel.checkInDateEnd.value = "" + viewModel.agentCode.value = "" + viewModel.spCode.value = "" + viewModel.destFilter.value = "" + viewModel.opUserFilter.value = "" + } + + /** 手机版筛选:确认 */ + fun confirmFilter() { + filterPanelVisible.set(false) + viewModel.searchClick() + } + companion object { @JvmStatic fun start(context: Context) { diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingStartActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingStartActivity.kt index 168ed21..937534d 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingStartActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingStartActivity.kt @@ -15,6 +15,7 @@ import com.lukouguoji.gjc.viewModel.GjcWeighingStartViewModel import com.lukouguoji.module_base.base.BaseBindingActivity import com.lukouguoji.module_base.common.Constant import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil /** * 国际出港计重-开始计重页面 @@ -32,26 +33,38 @@ class GjcWeighingStartActivity : override fun initOnCreate(savedInstanceState: Bundle?) { setBackArrow("国际出港开始计重") binding.viewModel = viewModel + + // 手机版专属:提交体携带托盘数量/托盘自重(平板不调用,请求体与改造前完全一致) + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } + viewModel.initOnCreated(this, intent) setupFloatButtons() } private fun setupFloatButtons() { + // 浮动按钮组仅平板布局存在(layout-sw600dp),手机布局无这些 id,直接跳过 + val mainFloatButton = binding.mainFloatButton ?: return + val maskView = binding.maskView ?: return + val subButton1 = binding.subButton1 ?: return + val subButton2 = binding.subButton2 ?: return + // 主按钮点击事件 - binding.mainFloatButton.setOnClickListener { + mainFloatButton.setOnClickListener { if (!isExpanded) { expandButtons() } } // 遮罩层点击事件 - binding.maskView.setOnClickListener { + maskView.setOnClickListener { collapseButtons() } // 子按钮1点击事件 - 跳转到出港运抵页面 - binding.subButton1.setOnClickListener { + subButton1.setOnClickListener { com.alibaba.android.arouter.launcher.ARouter.getInstance() .build(ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE) .navigation() @@ -59,7 +72,7 @@ class GjcWeighingStartActivity : } // 子按钮2点击事件 - 跳转到计重记录 - binding.subButton2.setOnClickListener { + subButton2.setOnClickListener { com.alibaba.android.arouter.launcher.ARouter.getInstance() .build(ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_LIST) .navigation() @@ -68,37 +81,42 @@ class GjcWeighingStartActivity : } /** - * 展开子按钮 + * 展开子按钮(仅平板,手机布局无浮动按钮组) */ private fun expandButtons() { + val mainFloatButton = binding.mainFloatButton ?: return + val maskView = binding.maskView ?: return + val subButton1 = binding.subButton1 ?: return + val subButton2 = binding.subButton2 ?: return + isExpanded = true // 显示遮罩层 - binding.maskView.visibility = View.VISIBLE - binding.maskView.alpha = 0f - binding.maskView.animate().alpha(0.3f).setDuration(200).start() + maskView.visibility = View.VISIBLE + maskView.alpha = 0f + maskView.animate().alpha(0.3f).setDuration(200).start() // 显示子按钮 - binding.subButton1.visibility = View.VISIBLE - binding.subButton2.visibility = View.VISIBLE + subButton1.visibility = View.VISIBLE + subButton2.visibility = View.VISIBLE // 子按钮1动画(向左上方移动: 左移15dp, 上移55dp) - val sub1TransX = ObjectAnimator.ofFloat(binding.subButton1, "translationX", 0f, -5f) - val sub1TransY = ObjectAnimator.ofFloat(binding.subButton1, "translationY", 0f, -25f) - val sub1Alpha = ObjectAnimator.ofFloat(binding.subButton1, "alpha", 0f, 1f) - val sub1Scale = ObjectAnimator.ofFloat(binding.subButton1, "scaleX", 0f, 1f) - val sub1ScaleY = ObjectAnimator.ofFloat(binding.subButton1, "scaleY", 0f, 1f) + val sub1TransX = ObjectAnimator.ofFloat(subButton1, "translationX", 0f, -5f) + val sub1TransY = ObjectAnimator.ofFloat(subButton1, "translationY", 0f, -25f) + val sub1Alpha = ObjectAnimator.ofFloat(subButton1, "alpha", 0f, 1f) + val sub1Scale = ObjectAnimator.ofFloat(subButton1, "scaleX", 0f, 1f) + val sub1ScaleY = ObjectAnimator.ofFloat(subButton1, "scaleY", 0f, 1f) val animSet1 = AnimatorSet() animSet1.playTogether(sub1TransX, sub1TransY, sub1Alpha, sub1Scale, sub1ScaleY) animSet1.duration = 200 // 子按钮2动画(向左下方移动: 左移55dp, 下移15dp) - val sub2TransX = ObjectAnimator.ofFloat(binding.subButton2, "translationX", 0f, -25f) - val sub2TransY = ObjectAnimator.ofFloat(binding.subButton2, "translationY", 0f, -5f) - val sub2Alpha = ObjectAnimator.ofFloat(binding.subButton2, "alpha", 0f, 1f) - val sub2Scale = ObjectAnimator.ofFloat(binding.subButton2, "scaleX", 0f, 1f) - val sub2ScaleY = ObjectAnimator.ofFloat(binding.subButton2, "scaleY", 0f, 1f) + val sub2TransX = ObjectAnimator.ofFloat(subButton2, "translationX", 0f, -25f) + val sub2TransY = ObjectAnimator.ofFloat(subButton2, "translationY", 0f, -5f) + val sub2Alpha = ObjectAnimator.ofFloat(subButton2, "alpha", 0f, 1f) + val sub2Scale = ObjectAnimator.ofFloat(subButton2, "scaleX", 0f, 1f) + val sub2ScaleY = ObjectAnimator.ofFloat(subButton2, "scaleY", 0f, 1f) val animSet2 = AnimatorSet() animSet2.playTogether(sub2TransX, sub2TransY, sub2Alpha, sub2Scale, sub2ScaleY) @@ -106,14 +124,14 @@ class GjcWeighingStartActivity : animSet2.startDelay = 50 // 主按钮隐藏动画 - binding.mainFloatButton.animate() + mainFloatButton.animate() .scaleX(0f) .scaleY(0f) .alpha(0f) .setDuration(150) .setListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { - binding.mainFloatButton.visibility = View.GONE + mainFloatButton.visibility = View.GONE } }) .start() @@ -123,33 +141,38 @@ class GjcWeighingStartActivity : } /** - * 收起子按钮 + * 收起子按钮(仅平板,手机布局无浮动按钮组) */ private fun collapseButtons() { + val mainFloatButton = binding.mainFloatButton ?: return + val maskView = binding.maskView ?: return + val subButton1 = binding.subButton1 ?: return + val subButton2 = binding.subButton2 ?: return + isExpanded = false // 隐藏遮罩层 - binding.maskView.animate().alpha(0f).setDuration(200).withEndAction { - binding.maskView.visibility = View.GONE + maskView.animate().alpha(0f).setDuration(200).withEndAction { + maskView.visibility = View.GONE }.start() // 子按钮1动画(回到原位) - val sub1TransX = ObjectAnimator.ofFloat(binding.subButton1, "translationX", binding.subButton1.translationX, 0f) - val sub1TransY = ObjectAnimator.ofFloat(binding.subButton1, "translationY", binding.subButton1.translationY, 0f) - val sub1Alpha = ObjectAnimator.ofFloat(binding.subButton1, "alpha", 1f, 0f) - val sub1Scale = ObjectAnimator.ofFloat(binding.subButton1, "scaleX", 1f, 0f) - val sub1ScaleY = ObjectAnimator.ofFloat(binding.subButton1, "scaleY", 1f, 0f) + val sub1TransX = ObjectAnimator.ofFloat(subButton1, "translationX", subButton1.translationX, 0f) + val sub1TransY = ObjectAnimator.ofFloat(subButton1, "translationY", subButton1.translationY, 0f) + val sub1Alpha = ObjectAnimator.ofFloat(subButton1, "alpha", 1f, 0f) + val sub1Scale = ObjectAnimator.ofFloat(subButton1, "scaleX", 1f, 0f) + val sub1ScaleY = ObjectAnimator.ofFloat(subButton1, "scaleY", 1f, 0f) val animSet1 = AnimatorSet() animSet1.playTogether(sub1TransX, sub1TransY, sub1Alpha, sub1Scale, sub1ScaleY) animSet1.duration = 200 // 子按钮2动画(回到原位) - val sub2TransX = ObjectAnimator.ofFloat(binding.subButton2, "translationX", binding.subButton2.translationX, 0f) - val sub2TransY = ObjectAnimator.ofFloat(binding.subButton2, "translationY", binding.subButton2.translationY, 0f) - val sub2Alpha = ObjectAnimator.ofFloat(binding.subButton2, "alpha", 1f, 0f) - val sub2Scale = ObjectAnimator.ofFloat(binding.subButton2, "scaleX", 1f, 0f) - val sub2ScaleY = ObjectAnimator.ofFloat(binding.subButton2, "scaleY", 1f, 0f) + val sub2TransX = ObjectAnimator.ofFloat(subButton2, "translationX", subButton2.translationX, 0f) + val sub2TransY = ObjectAnimator.ofFloat(subButton2, "translationY", subButton2.translationY, 0f) + val sub2Alpha = ObjectAnimator.ofFloat(subButton2, "alpha", 1f, 0f) + val sub2Scale = ObjectAnimator.ofFloat(subButton2, "scaleX", 1f, 0f) + val sub2ScaleY = ObjectAnimator.ofFloat(subButton2, "scaleY", 1f, 0f) val animSet2 = AnimatorSet() animSet2.playTogether(sub2TransX, sub2TransY, sub2Alpha, sub2Scale, sub2ScaleY) @@ -157,19 +180,19 @@ class GjcWeighingStartActivity : animSet1.addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { - binding.subButton1.visibility = View.GONE + subButton1.visibility = View.GONE } }) animSet2.addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { - binding.subButton2.visibility = View.GONE + subButton2.visibility = View.GONE } }) // 主按钮显示动画 - binding.mainFloatButton.visibility = View.VISIBLE - binding.mainFloatButton.animate() + mainFloatButton.visibility = View.VISIBLE + mainFloatButton.animate() .scaleX(1f) .scaleY(1f) .alpha(1f) diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingWbDetailActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingWbDetailActivity.kt new file mode 100644 index 0000000..906a9b2 --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingWbDetailActivity.kt @@ -0,0 +1,40 @@ +package com.lukouguoji.gjc.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityGjcWeighingWbDetailBinding +import com.lukouguoji.gjc.viewModel.GjcWeighingWbDetailViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.GjcWeighingRecordBean +import com.lukouguoji.module_base.common.Constant + +/** + * 国际出港计重-运单详情页(5.5寸手机版专属页面,平板端无对应页面) + * + * 由计重记录列表卡片的「查看详情」进入,只读展示运单基本信息, + * 对应设计稿 documents/5.5寸手持端设计文件/03_出港计重/detail.html。 + */ +class GjcWeighingWbDetailActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_gjc_weighing_wb_detail + + override fun viewModelClass() = GjcWeighingWbDetailViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("运单详情") + binding.viewModel = viewModel + viewModel.initOnCreated(intent) + } + + companion object { + @JvmStatic + fun start(context: Context, bean: GjcWeighingRecordBean) { + val starter = Intent(context, GjcWeighingWbDetailActivity::class.java) + .putExtra(Constant.Key.BEAN, bean) + context.startActivity(starter) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcCheckInRecordViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcCheckInRecordViewHolder.kt index 1b2a843..78f0876 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcCheckInRecordViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcCheckInRecordViewHolder.kt @@ -23,5 +23,10 @@ class GjcCheckInRecordViewHolder(view: View) : binding.isEditMode = isEditMode binding.position = position // 传入位置用于显示序号 binding.executePendingBindings() + + // 「修改」按钮(手机独有):打开全屏修改覆层编辑本条记录 + binding.btnEdit?.setOnClickListener { + activity?.openPhoneEdit(record) + } } } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingRecordViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingRecordViewHolder.kt index 93b41e5..bf3ae3c 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingRecordViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingRecordViewHolder.kt @@ -2,12 +2,17 @@ package com.lukouguoji.gjc.holder import android.view.View import com.lukouguoji.gjc.activity.GjcWeighingRecordDetailsActivity +import com.lukouguoji.gjc.activity.GjcWeighingWbDetailActivity import com.lukouguoji.gjc.databinding.ItemGjcWeighingRecordBinding import com.lukouguoji.module_base.base.BaseViewHolder import com.lukouguoji.module_base.bean.GjcWeighingRecordBean /** * 国际出港计重记录列表 ViewHolder + * + * item 布局分平板(layout-sw600dp/item_gjc_weighing_record.xml,含选择图标 iv_icon) + * 与手机(layout/item_gjc_weighing_record.xml,卡片式,地磅图标 iv_scale 进计重明细、 + * 「查看详情」tv_detail 进运单详情)两个变体,单侧独有的 id 需判空调用。 */ class GjcWeighingRecordViewHolder(view: View) : BaseViewHolder(view) { @@ -17,8 +22,8 @@ class GjcWeighingRecordViewHolder(view: View) : binding.bean = bean binding.executePendingBindings() - // 图标点击 - 切换选择状态 - binding.ivIcon.setOnClickListener { + // 图标点击 - 切换选择状态(平板独有) + binding.ivIcon?.setOnClickListener { // 反转checked状态 bean.checked.set(!bean.checked.get()) @@ -26,6 +31,16 @@ class GjcWeighingRecordViewHolder(view: View) : binding.executePendingBindings() } + // 地磅图标点击进计重明细(手机独有) + binding.ivScale?.setOnClickListener { + GjcWeighingRecordDetailsActivity.start(it.context, bean) + } + + // 「查看详情」进运单详情(手机独有页面) + binding.tvDetail?.setOnClickListener { + GjcWeighingWbDetailActivity.start(it.context, bean) + } + // 整行点击跳转到计重明细页 binding.ll.setOnClickListener { GjcWeighingRecordDetailsActivity.start(it.context, bean) diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingViewHolder.kt index 54e8513..9de45ad 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingViewHolder.kt @@ -1,15 +1,20 @@ package com.lukouguoji.gjc.holder import android.view.View +import com.lukouguoji.gjc.activity.GjcWeighingListActivity import com.lukouguoji.gjc.activity.GjcWeighingStartActivity import com.lukouguoji.gjc.databinding.ItemGjcWeighingBinding import com.lukouguoji.module_base.base.BaseViewHolder -import com.lukouguoji.module_base.common.ConstantEvent -import com.lukouguoji.module_base.impl.FlowBus +import com.lukouguoji.module_base.common.ConstantEvent +import com.lukouguoji.module_base.impl.FlowBus import com.lukouguoji.module_base.bean.GjcWeighingBean /** * 国际出港计重列表 ViewHolder + * + * item 布局分平板(layout-sw600dp/item_gjc_weighing.xml,含选择图标 iv_icon) + * 与手机(layout/item_gjc_weighing.xml,卡片式,含单票提前运抵按钮 btn_pre_arrive)两个变体, + * 单侧独有的 id 在 Binding 基类中为可空字段,需判空调用。 */ class GjcWeighingViewHolder(view: View) : BaseViewHolder(view) { @@ -20,8 +25,8 @@ class GjcWeighingViewHolder(view: View) : binding.position = position binding.executePendingBindings() - // 选择图标点击事件 - 切换选择状态 - binding.ivIcon.setOnClickListener { + // 选择图标点击事件 - 切换选择状态(平板独有) + binding.ivIcon?.setOnClickListener { // 反转checked状态 bean.checked.set(!bean.checked.get()) FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).tryEmit("check_changed") @@ -30,6 +35,11 @@ class GjcWeighingViewHolder(view: View) : binding.executePendingBindings() } + // 卡片内「提前运抵」按钮(手机独有,单票操作) + binding.btnPreArrive?.setOnClickListener { + (it.context as? GjcWeighingListActivity)?.preArriveClick(bean) + } + // 整行点击跳转到开始计重页面 binding.ll.setOnClickListener { GjcWeighingStartActivity.startForAdd(it.context, bean.maWbId) diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordDetailsViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordDetailsViewModel.kt index 7204d4e..7548180 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordDetailsViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordDetailsViewModel.kt @@ -53,6 +53,7 @@ class GjcWeighingRecordDetailsViewModel : BaseViewModel() { val totalPc = MutableLiveData("0") // 总件数 val totalWeight = MutableLiveData("0.0") // 总重量 val weightError = MutableLiveData("0.0%") // 重量误差百分比 + val totalCarWeight = MutableLiveData("0") // 托盘总重(5.5寸手机版顶部卡片,平板布局不引用) // 传递参数(用于API调用) private var prefix = "" @@ -143,6 +144,10 @@ class GjcWeighingRecordDetailsViewModel : BaseViewModel() { val sumWeight = records.sumOf { it.weight } totalWeight.value = String.format("%.2f", sumWeight) + // 计算托盘总重(手机版顶部卡片) + val sumCarWeight = records.sumOf { it.carWeight.toDoubleOrNull() ?: 0.0 } + totalCarWeight.value = String.format("%.2f", sumCarWeight) + // 计算重量误差百分比 val preWeightValue = preWeight.value?.toDoubleOrNull() ?: 0.0 val error = if (sumWeight > 0 && preWeightValue > 0) { @@ -191,6 +196,39 @@ class GjcWeighingRecordDetailsViewModel : BaseViewModel() { saveRecords(records) } + /** + * 5.5寸手机版「修改记录」覆层保存:与 [onSaveClick] 相同的批量更新接口, + * 但保存成功后留在本页(收起覆层 + 重新加载),不关闭页面。仅手机布局调用。 + */ + fun onPhoneSaveClick() { + val records = recordList.value ?: return + + if (!validateRecords(records)) return + + launchLoadingCollect({ + NetApply.api.updateGjcCheckInRecordList(records) + }) { + onSuccess = { result -> + if (result.data == true) { + showToast("保存成功") + // 收起编辑覆层 + isEditMode.value = false + // 通知列表页刷新 + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + // 重新加载本页数据 + loadData() + } else { + showToast("保存失败") + } + } + onFailed = { code, msg -> + showToast("保存失败:$msg") + } + } + } + /////////////////////////////////////////////////////////////////////////// // 业务逻辑 /////////////////////////////////////////////////////////////////////////// diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordViewModel.kt index 43897e9..65a195e 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordViewModel.kt @@ -46,6 +46,32 @@ class GjcWeighingRecordViewModel : BasePageViewModel() { val totalWeight = MutableLiveData("0") // 总重量 val cargoWeight = MutableLiveData("0") // 总货重 + // ========== 5.5寸手机版专属字段(平板不调用 initPhoneExtras,行为零变化) ========== + + /** 目的站(后端支持入参 dest) */ + val destFilter = MutableLiveData("") + + /** 计重人(后端支持入参 opId,下拉复用仓库用户列表) */ + val opUserFilter = MutableLiveData("") + val whsUserList = MutableLiveData>(emptyList()) + + /** 入库日期起/止(后端暂无对应入参,传 opDateStart/opDateEnd 预留参数,见接口问题清单) */ + val checkInDateStart = MutableLiveData("") + val checkInDateEnd = MutableLiveData("") + + /** 由手机形态的 Activity 置 true,平板保持 false(不产生任何额外请求与参数) */ + private var phoneExtrasEnabled = false + + /** + * 开启手机版专属数据:放开「今天」默认日期(设计稿筛选无航班日期)、加载计重人下拉。 + * 仅由手机形态的 Activity 调用。 + */ + fun initPhoneExtras() { + phoneExtrasEnabled = true + flightDate.value = "" + DictUtils.getWHSUserList { whsUserList.postValue(it) } + } + /////////////////////////////////////////////////////////////////////////// // 方法区 /////////////////////////////////////////////////////////////////////////// @@ -130,25 +156,38 @@ class GjcWeighingRecordViewModel : BasePageViewModel() { * 获取列表数据 */ override fun getData() { + // 公共查询条件(列表与统计共用) + val baseParams = mutableMapOf( + "fdate" to flightDate.value!!.ifEmpty { null }, + "fno" to flightNo.value!!.ifEmpty { null }, + "agentCode" to agentCode.value!!.ifEmpty { null }, + "spCode" to spCode.value!!.ifEmpty { null }, + "wbNo" to waybillNo.value!!.ifEmpty { null }, + ) + + // 手机版专属条件(平板 phoneExtrasEnabled 恒为 false,请求体与改造前完全一致) + if (phoneExtrasEnabled) { + // 搜索分流(实测):11 位数字走 wbNo 精确;其余走 likeNo(后端按 8 位 no 匹配) + val key = waybillNo.value?.trim() ?: "" + if (key.isNotEmpty() && key.length != 11) { + baseParams["wbNo"] = null + baseParams["likeNo"] = key + } + baseParams["dest"] = destFilter.value?.ifEmpty { null } + baseParams["opId"] = opUserFilter.value?.ifEmpty { null } + // 入库日期起/止为后端预留参数(暂无对应入参,静默忽略,见接口问题清单) + baseParams["opDateStart"] = checkInDateStart.value?.ifEmpty { null } + baseParams["opDateEnd"] = checkInDateEnd.value?.ifEmpty { null } + } + // 构建查询参数(列表接口) - val listParams = mapOf( + val listParams = (baseParams + mapOf( "pageNum" to pageModel.page, "pageSize" to pageModel.limit, - "fdate" to flightDate.value!!.ifEmpty { null }, - "fno" to flightNo.value!!.ifEmpty { null }, - "agentCode" to agentCode.value!!.ifEmpty { null }, - "spCode" to spCode.value!!.ifEmpty { null }, - "wbNo" to waybillNo.value!!.ifEmpty { null }, - ).toRequestBody() + )).toRequestBody() // 构建查询参数(统计接口 - 使用相同的搜索条件) - val totalParams = mapOf( - "fdate" to flightDate.value!!.ifEmpty { null }, - "fno" to flightNo.value!!.ifEmpty { null }, - "agentCode" to agentCode.value!!.ifEmpty { null }, - "spCode" to spCode.value!!.ifEmpty { null }, - "wbNo" to waybillNo.value!!.ifEmpty { null }, - ).toRequestBody() + val totalParams = baseParams.toRequestBody() // 获取列表数据(显示loading) launchLoadingCollect({ diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingStartViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingStartViewModel.kt index fa338d6..fc45172 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingStartViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingStartViewModel.kt @@ -72,9 +72,22 @@ class GjcWeighingStartViewModel : BaseViewModel() { val spCodeList = MutableLiveData>() // 特码列表 val businessTypeList = MutableLiveData>() // 业务类型列表 - // 托盘车自重(查询获取) + // 托盘车自重(平板:托盘车号查询回填只读;手机:手输,见下方 initPhoneExtras) val carWeight = MutableLiveData("0") + // ========== 5.5寸手机版专属(平板不调用 initPhoneExtras,行为零变化) ========== + + /** 托盘数量(设计稿字段,后端暂无对应入参,提交时传 palletNumber 预留参数,见接口问题清单) */ + val palletNumber = MutableLiveData("") + + /** 手机形态标记:为 true 时提交体额外携带 palletNumber / carWeight(后端静默忽略) */ + private var phoneMode = false + + /** 仅由手机形态的 Activity 调用 */ + fun initPhoneExtras() { + phoneMode = true + } + /** * 初始化 */ @@ -392,6 +405,12 @@ class GjcWeighingStartViewModel : BaseViewModel() { passageWayId = this@GjcWeighingStartViewModel.channel.value remark = pageRemark.value + + // 手机版专属:托盘数量/托盘自重(后端暂无对应入参,静默忽略;平板 phoneMode 恒 false,字段为 null 不进请求体) + if (this@GjcWeighingStartViewModel.phoneMode) { + palletNumber = this@GjcWeighingStartViewModel.palletNumber.value?.ifEmpty { null } + carWeight = this@GjcWeighingStartViewModel.carWeight.value?.ifEmpty { null } + } } // 3. 构建请求数据(GjcMaWb转RequestBody,包含通道号) @@ -423,8 +442,10 @@ class GjcWeighingStartViewModel : BaseViewModel() { maWbBean.value = maWbBean.value?.apply { carId = null remark = null + palletNumber = null } carWeight.value = "0" + this@GjcWeighingStartViewModel.palletNumber.value = "" } else { showToast(result.msg.noNull("分托计重失败")) } @@ -502,7 +523,10 @@ class GjcWeighingStartViewModel : BaseViewModel() { "remark" to pageRemark.value, "checkIn" to "1", // 收运状态设置为已收运 "passageWayId" to channel.value, // 通道号参数 - "passageWay" to (channelList.value?.firstOrNull{ it.value == channel.value }?.key ?: "") + "passageWay" to (channelList.value?.firstOrNull{ it.value == channel.value }?.key ?: ""), + // 手机版专属预留参数(平板 phoneMode 恒 false → null → removeEmptyOrNull 移除,请求体不变) + "palletNumber" to (if (phoneMode) palletNumber.value?.ifEmpty { null } else null), + "carWeight" to (if (phoneMode) carWeight.value?.ifEmpty { null } else null) ).toRequestBody(removeEmptyOrNull = true) launchLoadingCollect({ diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingViewModel.kt index 0559c43..feabb0f 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingViewModel.kt @@ -55,15 +55,80 @@ class GjcWeighingViewModel : BasePageViewModel() { // 全选状态 val isAllChecked = MutableLiveData(false) - - fun onItemCheckChanged() { - updateCheckAllStatus() - } - - fun updateCheckAllStatus() { - val list = pageModel.rv?.commonAdapter()?.items as? List ?: return - isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() } - } + + // ========== 5.5寸手机版专属字段(平板不调用 initPhoneExtras,行为零变化) ========== + + /** 手机版顶部搜索关键字(运单号/航班号混输,getData 内分流:含字母→fno,纯数字→likeNo 模糊) */ + val searchKey = MutableLiveData("") + + /** 主页三格统计:待计重(checkIn=0)/ 计重中(checkIn=2)数量 */ + val pendingCount = MutableLiveData("0") + val weighingCount = MutableLiveData("0") + + /** 手机版筛选弹层字段。通道号/承运人/运单类型后端暂无查询入参(见接口问题清单),传预留参数名 */ + val channelFilter = MutableLiveData("") // 通道号 → passageWayId + val carrierFilter = MutableLiveData("") // 承运人 → by0 + val awbTypeFilter = MutableLiveData("") // 运单类型 → awbType + val channelList = MutableLiveData>(emptyList()) + val awbTypeList = MutableLiveData>(emptyList()) + + /** 由手机形态的 Activity 置 true,平板保持 false(不产生任何额外请求与参数) */ + private var phoneExtrasEnabled = false + + /** + * 开启手机版专属数据:放开「今天」默认日期(设计稿主页无日期筛选)、加载筛选弹层字典。 + * 仅由手机形态的 Activity 调用。 + */ + fun initPhoneExtras() { + phoneExtrasEnabled = true + flightDate.value = "" + DictUtils.getGjcChannelList { list -> + channelList.postValue(listOf(KeyValue("全部", "")) + list) + } + DictUtils.getWaybillTypeList2(ieFlag = "E", type = "IO") { + awbTypeList.postValue(it) + } + } + + /** + * 单票提前运抵(手机版卡片内按钮;平板走底部批量 [arrivedAhead]) + */ + fun arrivedAheadSingle(bean: GjcWeighingBean) { + if (bean.arriveFlag == "1") { + showToast("该运单已提前运抵") + return + } + val maWbList = listOf( + GjcMaWb( + maWbId = bean.maWbId, + no = bean.no, + prefix = bean.prefix, + wbNo = bean.wbNo, + arriveFlag = "1" + ) + ) + launchLoadingCollect({ NetApply.api.preArrive(maWbList) }) { + onSuccess = { + showToast("提前运抵成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + refresh() + } + onFailed = { code, msg -> + showToast(msg.noNull("提前运抵失败")) + } + } + } + + fun onItemCheckChanged() { + updateCheckAllStatus() + } + + fun updateCheckAllStatus() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() } + } /////////////////////////////////////////////////////////////////////////// // 方法区 @@ -185,25 +250,41 @@ class GjcWeighingViewModel : BasePageViewModel() { * 获取列表数据 */ override fun getData() { + // 公共查询条件(列表与统计共用) + val baseParams = mutableMapOf( + "fdate" to flightDate.value!!.ifEmpty { null }, + "fno" to flightNo.value!!.ifEmpty { null }, + "agentCode" to agentCode.value!!.ifEmpty { null }, + "spCode" to spCode.value!!.ifEmpty { null }, + "wbNo" to waybillNo.value!!.ifEmpty { null }, + ) + + // 手机版专属条件(平板 phoneExtrasEnabled 恒为 false,请求体与改造前完全一致) + if (phoneExtrasEnabled) { + val key = searchKey.value?.trim() ?: "" + if (key.isNotEmpty()) { + // 分流规则(实测):含字母 → 航班号;11 位数字 → wbNo 精确; + // 其余数字 → likeNo(后端按 8 位 no 匹配,并非任意模糊) + when { + key.any { it.isLetter() } -> baseParams["fno"] = key + key.length == 11 -> baseParams["wbNo"] = key + else -> baseParams["likeNo"] = key + } + } + // 以下三个为后端预留参数(暂无对应入参,后端静默忽略,见接口问题清单) + baseParams["passageWayId"] = channelFilter.value?.ifEmpty { null } + baseParams["by0"] = carrierFilter.value?.ifEmpty { null } + baseParams["awbType"] = awbTypeFilter.value?.ifEmpty { null } + } + // 构建查询参数(列表接口) - val listParams = mapOf( + val listParams = (baseParams + mapOf( "pageNum" to pageModel.page, "pageSize" to pageModel.limit, - "fdate" to flightDate.value!!.ifEmpty { null }, - "fno" to flightNo.value!!.ifEmpty { null }, - "agentCode" to agentCode.value!!.ifEmpty { null }, - "spCode" to spCode.value!!.ifEmpty { null }, - "wbNo" to waybillNo.value!!.ifEmpty { null }, - ).toRequestBody() + )).toRequestBody() // 构建查询参数(统计接口 - 使用相同的搜索条件) - val totalParams = mapOf( - "fdate" to flightDate.value!!.ifEmpty { null }, - "fno" to flightNo.value!!.ifEmpty { null }, - "agentCode" to agentCode.value!!.ifEmpty { null }, - "spCode" to spCode.value!!.ifEmpty { null }, - "wbNo" to waybillNo.value!!.ifEmpty { null }, - ).toRequestBody() + val totalParams = baseParams.toRequestBody() // 获取列表数据(显示loading) launchLoadingCollect({ @@ -225,6 +306,21 @@ class GjcWeighingViewModel : BasePageViewModel() { totalWeight.value = (data?.totalWeight ?: 0.0).toString() } } + + // 手机版三格统计:待计重 / 计重中(各带一次 checkIn 条件的统计请求,仅手机调用) + if (phoneExtrasEnabled) { + listOf("0" to pendingCount, "2" to weighingCount).forEach { (state, liveData) -> + launchCollect({ + NetApply.api.getGjcWeighingStatistics( + (baseParams + mapOf("checkIn" to state)).toRequestBody() + ) + }) { + onSuccess = { result -> + liveData.value = (result.data?.wbNumber ?: 0).toString() + } + } + } + } } /** @@ -234,7 +330,10 @@ class GjcWeighingViewModel : BasePageViewModel() { if (resultCode == Activity.RESULT_OK && data != null) { when (requestCode) { Constant.RequestCode.WAYBILL -> { - waybillNo.value = data.getStringExtra(Constant.Result.CODED_CONTENT) + val content = data.getStringExtra(Constant.Result.CODED_CONTENT) + // 手机版扫码写入顶部搜索框,平板写入原运单号搜索条 + if (phoneExtrasEnabled) searchKey.value = content + else waybillNo.value = content refresh() } } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingWbDetailViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingWbDetailViewModel.kt new file mode 100644 index 0000000..0de37cf --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingWbDetailViewModel.kt @@ -0,0 +1,30 @@ +package com.lukouguoji.gjc.viewModel + +import android.content.Intent +import androidx.lifecycle.MutableLiveData +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.GjcWeighingRecordBean +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.ktx.showToast + +/** + * 国际出港计重-运单详情 ViewModel(5.5寸手机版专属页面) + * + * 只读展示计重记录列表传入的运单信息,无接口请求。 + * 注:设计稿中的「通道号」字段在 /IntExpCheckIn/checked/pageQuery 出参中不存在(后端缺口, + * 见接口问题清单),布局侧空值兜底显示 "-"。 + */ +class GjcWeighingWbDetailViewModel : BaseViewModel() { + + // 运单信息(从计重记录列表页传入) + val bean = MutableLiveData(GjcWeighingRecordBean()) + + fun initOnCreated(intent: Intent) { + val data = intent.getSerializableExtra(Constant.Key.BEAN) as? GjcWeighingRecordBean + if (data != null) { + bean.value = data + } else { + showToast("参数错误") + } + } +} diff --git a/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_list.xml b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_list.xml new file mode 100644 index 0000000..353f09f --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_list.xml @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_record_details.xml b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_record_details.xml new file mode 100644 index 0000000..f3fca7f --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_record_details.xml @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_record_list.xml b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_record_list.xml new file mode 100644 index 0000000..0f8db9d --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_record_list.xml @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_start.xml b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_start.xml new file mode 100644 index 0000000..3e036fe --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_start.xml @@ -0,0 +1,496 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/item_gjc_check_in_record.xml b/module_gjc/src/main/res/layout-sw600dp/item_gjc_check_in_record.xml new file mode 100644 index 0000000..e1fcc60 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/item_gjc_check_in_record.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/item_gjc_weighing.xml b/module_gjc/src/main/res/layout-sw600dp/item_gjc_weighing.xml new file mode 100644 index 0000000..3723c6a --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/item_gjc_weighing.xml @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/item_gjc_weighing_record.xml b/module_gjc/src/main/res/layout-sw600dp/item_gjc_weighing_record.xml new file mode 100644 index 0000000..e1e8d7c --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/item_gjc_weighing_record.xml @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_gjc_weighing_list.xml b/module_gjc/src/main/res/layout/activity_gjc_weighing_list.xml index 165cefc..f397371 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_weighing_list.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_weighing_list.xml @@ -1,222 +1,301 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_gjc_weighing_record_details.xml b/module_gjc/src/main/res/layout/activity_gjc_weighing_record_details.xml index 0c5d9f8..b6405b0 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_weighing_record_details.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_weighing_record_details.xml @@ -1,270 +1,257 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_gjc_weighing_record_list.xml b/module_gjc/src/main/res/layout/activity_gjc_weighing_record_list.xml index 381001f..20c4e3c 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_weighing_record_list.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_weighing_record_list.xml @@ -1,183 +1,301 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml b/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml index 3e036fe..c798f17 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml @@ -1,496 +1,286 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_gjc_weighing_wb_detail.xml b/module_gjc/src/main/res/layout/activity_gjc_weighing_wb_detail.xml new file mode 100644 index 0000000..54f9593 --- /dev/null +++ b/module_gjc/src/main/res/layout/activity_gjc_weighing_wb_detail.xml @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_gjc_check_in_record.xml b/module_gjc/src/main/res/layout/item_gjc_check_in_record.xml index e1fcc60..79ff69a 100644 --- a/module_gjc/src/main/res/layout/item_gjc_check_in_record.xml +++ b/module_gjc/src/main/res/layout/item_gjc_check_in_record.xml @@ -1,95 +1,196 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_gjc_weighing.xml b/module_gjc/src/main/res/layout/item_gjc_weighing.xml index 3723c6a..12b55aa 100644 --- a/module_gjc/src/main/res/layout/item_gjc_weighing.xml +++ b/module_gjc/src/main/res/layout/item_gjc_weighing.xml @@ -1,316 +1,141 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_gjc_weighing_record.xml b/module_gjc/src/main/res/layout/item_gjc_weighing_record.xml index e1e8d7c..8f23284 100644 --- a/module_gjc/src/main/res/layout/item_gjc_weighing_record.xml +++ b/module_gjc/src/main/res/layout/item_gjc_weighing_record.xml @@ -1,272 +1,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 6bcb6af..15e7b15 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,12 @@ class GjViewModel : BaseViewModel() { Constant.AuthName.GjcIntExpOutHandover, ARouterConstants.ACTIVITY_URL_INT_EXP_OUT_HANDOVER ), + ActionBean( + "出港计重", + R.drawable.img_gjc_chugangjizhong, + Constant.AuthName.GjcCheckWeighing, + ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_LIST + ), // ULD管理属综合管理业务(Pad 端在「综合管理」菜单组),手机端首页暂无综合 Tab,挂在国际 Tab 下 ActionBean( "ULD管理", diff --git a/module_p/src/main/res/drawable-xxhdpi/img_gjc_chugangjizhong.png b/module_p/src/main/res/drawable-xxhdpi/img_gjc_chugangjizhong.png new file mode 100644 index 0000000000000000000000000000000000000000..57ab8e4a4bffbba83b753f02a2db55193cb6a944 GIT binary patch literal 31892 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 iC>SvivYPZ^DeT7E-oshk;ypuKw+6b#I+ Date: Thu, 30 Jul 2026 11:44:51 +0800 Subject: [PATCH 05/29] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=87=BA?= =?UTF-8?q?=E6=B8=AF=E8=BF=90=E6=8A=B5=E9=A1=B5=E9=9D=A25.5=E5=AF=B8?= =?UTF-8?q?=E6=89=8B=E6=9C=BA=E7=AB=AF=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 主列表新增待运抵/已运抵 Tab(客户端按申报状态拆分)+ 卡片长按浮层(补充/重置/回执) - 新增分单明细页:复用主列表已加载数据,零新增请求 - 新增回执内容只读页 - 新增补充信息页:参照 Pad 端收发货人信息批量应用模式(后端接口暂缺,已登记问题清单) - 手机首页「国际」Tab 增加「出港运抵」入口 - 修复两个平台坑:RecyclerView 内 GONE 不塌陷高度;Serializable Intent 传递 遇 @Transient 字段反序列化为 null 导致的崩溃 - 登记后端接口缺口 2 项(#19~#20)至问题清单 Co-Authored-By: Claude Opus 4.6 --- .../skills/phone-adapt/references/api-doc.md | 7 + .../phone-adapt/references/pad-safety.md | 94 ++- CHANGELOG.md | 31 + CLAUDE.md | 14 + app/src/debug/AndroidManifest.xml | 24 + app/src/main/AndroidManifest.xml | 18 + documents/后端接口对接问题清单.xlsx | Bin 16942 -> 19513 bytes .../lukouguoji/module_base/bean/GjcMaWb.kt | 43 +- .../lukouguoji/module_base/http/net/Api.kt | 10 + .../main/res/drawable/bg_phone_fab_amber.xml | 6 + .../main/res/drawable/bg_phone_fab_green.xml | 6 + .../main/res/drawable/bg_phone_fab_purple.xml | 6 + .../main/res/drawable/bg_phone_tag_amber.xml | 7 + .../main/res/drawable/bg_phone_tag_indigo.xml | 7 + module_base/src/main/res/values/colors.xml | 4 + .../gjc/activity/IntExpArriveActivity.kt | 94 +++ .../activity/IntExpArriveReceiptActivity.kt | 43 + .../activity/IntExpArriveSubOrderActivity.kt | 92 +++ .../IntExpArriveSupplementActivity.kt | 41 + .../holder/IntExpArriveReceiptViewHolder.kt | 19 + .../holder/IntExpArriveSubOrderViewHolder.kt | 32 + .../gjc/holder/IntExpArriveViewHolder.kt | 50 +- .../viewModel/IntExpArriveReceiptViewModel.kt | 34 + .../IntExpArriveSubOrderViewModel.kt | 137 +++ .../IntExpArriveSupplementViewModel.kt | 119 +++ .../gjc/viewModel/IntExpArriveViewModel.kt | 151 +++- .../activity_int_exp_arrive.xml | 244 ++++++ .../layout-sw600dp/item_int_exp_arrive.xml | 520 ++++++++++++ .../res/layout/activity_int_exp_arrive.xml | 400 ++++----- .../activity_int_exp_arrive_receipt.xml | 44 + .../activity_int_exp_arrive_sub_order.xml | 114 +++ .../activity_int_exp_arrive_supplement.xml | 219 +++++ .../main/res/layout/item_int_exp_arrive.xml | 777 ++++++------------ .../layout/item_int_exp_arrive_receipt.xml | 57 ++ .../layout/item_int_exp_arrive_sub_order.xml | 130 +++ .../sixin/module_p/ui/enter/gj/GjViewModel.kt | 6 + .../drawable-xxhdpi/img_gjc_chugang_diyun.png | Bin 0 -> 33013 bytes 37 files changed, 2825 insertions(+), 775 deletions(-) create mode 100644 module_base/src/main/res/drawable/bg_phone_fab_amber.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_fab_green.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_fab_purple.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_tag_amber.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_tag_indigo.xml create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveReceiptActivity.kt create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSubOrderActivity.kt create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSupplementActivity.kt create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveReceiptViewHolder.kt create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveSubOrderViewHolder.kt create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveReceiptViewModel.kt create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveSubOrderViewModel.kt create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveSupplementViewModel.kt create mode 100644 module_gjc/src/main/res/layout-sw600dp/activity_int_exp_arrive.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/item_int_exp_arrive.xml create mode 100644 module_gjc/src/main/res/layout/activity_int_exp_arrive_receipt.xml create mode 100644 module_gjc/src/main/res/layout/activity_int_exp_arrive_sub_order.xml create mode 100644 module_gjc/src/main/res/layout/activity_int_exp_arrive_supplement.xml create mode 100644 module_gjc/src/main/res/layout/item_int_exp_arrive_receipt.xml create mode 100644 module_gjc/src/main/res/layout/item_int_exp_arrive_sub_order.xml create mode 100644 module_p/src/main/res/drawable-xxhdpi/img_gjc_chugang_diyun.png diff --git a/.claude/skills/phone-adapt/references/api-doc.md b/.claude/skills/phone-adapt/references/api-doc.md index 8634cee..6570f2e 100644 --- a/.claude/skills/phone-adapt/references/api-doc.md +++ b/.claude/skills/phone-adapt/references/api-doc.md @@ -70,6 +70,13 @@ curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \ 0 正常/1 故障(三态需求=缺口 #7);无「来源」字段(#8)、无 `checkInDate`/`ifNo` 筛选入参(#9)、 无批量删除(#10,`deleteUld` 是 `@Query` 单条);出参 `ifNo`/`efNo`/`checkInDate`/`checkOutDate` 文档无描述,按命名推断进/出港航班号与出入库时间(#11 待确认) +- `IntExpArrive`(出港运抵,2026-07-30 内网实测):`declareStatus`(申报状态)只在出参, + `pageQuery`/`pageQueryTotal` 入参均无此字段(缺口 #20,待运抵/已运抵 Tab 靠客户端拆分); + `declareStatus`/`GjcHaWb.arrivalStatus` 三色编码:`01`=正常(绿)、`W`=靛蓝态、其余非空=琥珀异常态; + `haWbList[].response`/`arrivalOpDate` 是回执文本与对应时间,实测确认真实存在非空数据; + 分单补充收发货人信息**后端完全没有对应接口**(`search_endpoints` 对 `IntExpArrive`/`HaWb` + 关键字均搜不到分单更新接口,只有国际进港的 `IntImpAirManifest/complete`), + 实机调用拟定路径 `IntExpArrive/haWb/supplement` 确认 404(缺口 #19) - `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/pad-safety.md b/.claude/skills/phone-adapt/references/pad-safety.md index 9cc07d5..5c30f26 100644 --- a/.claude/skills/phone-adapt/references/pad-safety.md +++ b/.claude/skills/phone-adapt/references/pad-safety.md @@ -130,7 +130,7 @@ binding.btnMove?.setOnClickListener { showMoveConfirmDialog() } 例:手机「待交接」Tab 下理论上只有未交接记录(服务端按状态过滤),所以全选照原样全量勾选就是对的; 若为此加上「跳过已交接」的过滤,反而改变了平板端(平板列表混排两种状态)的行为。 -## 屏幕方向:Manifest 必须写资源引用 +## 屏幕方向:Manifest 一律写 `unspecified` 新增 Activity 注册时: @@ -138,15 +138,20 @@ binding.btnMove?.setOnClickListener { showMoveConfirmDialog() } + android:screenOrientation="unspecified" /> ``` -**不要写死 `userLandscape`。** `screenOrientation` 由系统在创建 Activity 窗口时生效, -那时业务代码还没跑;写死横屏后即使 `BaseActivity` 在 `super.onCreate` 之前改成竖屏, -用户也会看到「先横屏、约 1 秒后转竖屏」的闪屏和重建。 +**两种错误方案都实测踩过,别再试:** +- 写死 `userLandscape` → 手机「先横屏、约 1 秒后转竖屏」(方向在建窗口时就定了, + `BaseActivity` 在 `super.onCreate` 之前纠正也来不及) +- 用 `@integer/screen_orientation` 资源引用(曾经以为是优雅方案)→ **更糟**:系统解析 + Manifest 属性不套用设备限定符,所有 Activity 实际都拿到 `values/` 默认值(竖屏), + 平板因此先竖后横,且 AutoSize 在竖屏配置下选中平板竖屏 720dp 基准 + (正常应为 1152×720 横屏基准),交互几次后整个 UI 放大约 1.6 倍 -资源取值:`module_base/res/values/integers.xml` = 1(portrait), -`values-sw600dp/integers.xml` = 11(userLandscape)。全项目已统一替换。 +`unspecified` 让系统按设备当前物理方向建窗口(平板横屏摆放→横屏起,手机→竖屏起, +两端起始方向本就正确),`BaseActivity.applyDeviceOrientation()` 再按形态锁定, +不产生二次纠正。全项目 192 处已统一为 `unspecified`。 ## 改 module_base 公共代码时 @@ -158,6 +163,81 @@ binding.btnMove?.setOnClickListener { showMoveConfirmDialog() } - Bean 上加只读计算属性是安全的(Gson 只序列化字段,不动 getter); 加**字段**要谨慎,会进请求体 +## RecyclerView 里不要用 item 级 visibility 做 Tab/分类过滤 + +普通 ViewGroup(LinearLayout 等)里 `View.GONE` 的子 View 会自动塌陷为 0 高度、不占布局空间—— +但 **RecyclerView + LinearLayoutManager 不是这样**:它按子项的测量高度参与滚动区域计算, +不会因为子项是 GONE 就跳过。给 item 根节点加 `visibility="@{tab条件 ? VISIBLE : GONE}"` +切 Tab,会在列表里留下一段空白(隐藏项的高度仍被保留),角标数字和实际卡片数量对不上。 + +出港运抵的「待运抵/已运抵」Tab 就踩了这个坑(实机截图验证:切到「已运抵」后顶部有一大块 +空白,隐藏的待运抵卡片高度并未塌陷)。正确做法是在数据层过滤,而不是视图层: + +```kotlin +// ViewModel:自己维护完整列表,不依赖 adapter.items 的历史状态 +// (见下一节:adapter.items 在 loadMore 场景可能已经是上次过滤后的子集,不能当作真源) +private var allLoadedList: List = emptyList() + +override fun getData() { + launchLoadingCollect({ ... }) { + onSuccess = { result -> + val newPageItems = result.list ?: emptyList() + allLoadedList = if (pageModel.page <= 1) newPageItems else allLoadedList + newPageItems + + pageModel.handleListBean(result) { + // 无论 handleListBean 内部把 adapter.items 搞成什么样,这里用 allLoadedList + // 强制覆盖为「当前 Tab 的正确子集」,兜底纠正 + val filtered = allLoadedList.filter { it.isPending == (currentTab.value == "pending") } + pageModel.rv?.commonAdapter()?.refresh(filtered) + } + } + } +} + +fun onTabChangedPhone() { + val filtered = allLoadedList.filter { it.isPending == (currentTab.value == "pending") } + pageModel.rv?.commonAdapter()?.refresh(filtered) // 只是 items.clear()+addAll()+notifyDataSetChanged,无副作用 +} +``` + +`CommonAdapter.refresh()` 只是替换内部列表并 `notifyDataSetChanged()`,不影响 +SmartRefreshLayout 的分页/完成状态,可以放心在 `handleListBean` 回调里再调用一次。 + +## Intent 传递 Serializable Bean:`@Transient` 字段反序列化后是 null + +`GjcMaWb`/`GjcHaWb` 的 `checked`/`showMore`/`actionMenuVisible` 三个 UI 状态字段都标了 +`@Transient`(本意是避免 Gson 把 `ObservableBoolean` 的内部结构序列化进网络请求体)。 +但 Kotlin 的 `@Transient` 注解生成的就是 JVM 的 `transient` 修饰符,这个修饰符对 **Java +对象序列化**(`Intent.putExtra(String, Serializable)` 走的正是这条路径)有实际含义: +反序列化时会跳过 `transient` 字段的恢复,对象引用类型的字段结果就是 **null**。 + +新增手机专属页面时,如果要把 `List` 通过 `ArrayList` 塞进 `Intent` +传给下一个页面,接收方拿到的对象「看起来」字段都对(wbNo、pc、weight 这些正常字段没问题, +因为它们不是 `@Transient`),但只要调用 `bean.checked.set(...)` 就会立刻崩溃: + +``` +NullPointerException: Attempt to invoke virtual method +'void androidx.databinding.ObservableBoolean.set(boolean)' on a null object reference +``` + +出港运抵的「分单明细」页第一版全选按钮就是这样崩的。**修复只需一行**,在接收方 +`initOnCreated` 里对拿到的列表整体 `.copy()` 一遍——`.copy()` 会重新触发一次真正的对象构造, +类体里 `val checked = ObservableBoolean(false)` 这类初始化逻辑跟着重新跑一遍, +把 null 补成全新实例: + +```kotlin +@Suppress("UNCHECKED_CAST") +fun initOnCreated(intent: Intent) { + val list = intent.getSerializableExtra(Constant.Key.DATA) as? ArrayList + // .copy() 补上被 Java 序列化跳过的 @Transient 字段 + fullList = (list ?: emptyList()).map { it.copy() } +} +``` + +这个坑只在「Intent 传递 Serializable Bean + 接收方要切换 checked/showMore 等状态」时才会 +触发;纯只读展示(如回执页)不调用这些字段的 setter,不会崩,但补一道 `.copy()` 无害, +建议只要通过 Intent 传了 haWbList/maWbList 就统一加上,别等下次踩到才想起来。 + ## 已知的既有问题(不是你改坏的) 用 `am start` 直启页面时,若**先经过首页**再启目标页,会崩在 diff --git a/CHANGELOG.md b/CHANGELOG.md index c2753ac..73ea40e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,37 @@ ## [Unreleased] ### 新增 (Added) +- 「出港运抵」5.5 寸手机端适配(主列表 + 3 个手机专属新页,设计稿 04_出港运抵): + 主列表 `IntExpArriveActivity` 新增「待运抵/已运抵」Tab(客户端按 declareStatus 是否为空拆分数据集, + 接口无此查询参数)+ 卡片长按浮层(待运抵→补充、已运抵→重置+回执,纯 UI 长按)+ 底部全选/已选/申报 + (仅待运抵 Tab 显示,选中范围独立于 Pad 全量选择逻辑);新增「分单明细」`IntExpArriveSubOrderActivity` + (数据直接复用主列表已加载的 haWbList,零新增请求,长按单条重置 + 底部批量申报);新增「回执内容」 + `IntExpArriveReceiptActivity`(只读页,复用 haWbList[].response + arrivalOpDate);新增「补充信息」 + `IntExpArriveSupplementActivity`(参照 Pad 端国际进港「收发货人信息」批量应用模式,对整个运单的 + haWbList 批量应用同一份表单,后端接口不存在,已实机确认 404,见问题清单 #19) +- 手机首页「国际」Tab 增加「出港运抵」入口 +- `GjcMaWb`/`GjcHaWb` 新增 `isPending`/`declareTagColor`/`haWbTagColor`/`arrivalOpDateText` 等 + 手机版专属计算属性;`GjcHaWb` 补充 `Serializable` 实现(供 Intent 跨页传递分单列表) +- 新增手机版资源:`bg_phone_tag_indigo`/`bg_phone_tag_amber`(申报状态三色标签)、 + `bg_phone_fab_purple`/`bg_phone_fab_amber`/`bg_phone_fab_green`(长按浮层圆形操作按钮) +- 后端缺口 2 项登记问题清单 #19~#20(分单补充信息保存接口不存在、Tab 无申报状态查询参数) + +### 修复 (Fixed) +- **RecyclerView + Tab 过滤新坑**:给 item 根节点加 `visibility="@{...}"` 切 Tab 会在列表里 + 留下空白——RecyclerView/LinearLayoutManager 不像普通 ViewGroup 那样让 GONE 子项自动塌陷为 + 0 高度。改为在 ViewModel 数据层维护完整列表,Tab 切换时把过滤后的子集整体 `refresh()` 给 + adapter(已实机截图验证空白消失、卡片数与角标一致) +- **Serializable Intent + @Transient 崩溃新坑**:`GjcMaWb`/`GjcHaWb` 的 `checked` 等 UI 状态 + 字段标了 `@Transient`(避免 Gson 序列化 ObservableBoolean),但这同时是 JVM `transient` + 修饰符,Java 序列化(Intent 传递机制)会跳过其恢复,反序列化后为 null,切换选中状态时 + NullPointerException 崩溃。修复:接收方 `initOnCreated` 对列表 `.map { it.copy() }` 重新 + 触发类体初始化补上(已实机崩溃复现并验证修复) + +### 验证 (Verified) +- 出港运抵双端实机验证通过:手机端 Tab 切换(角标/卡片双向正确)/全选/单选/长按菜单/查看分单 + /分单明细全选与长按重置/补充信息(真实数据回填+下拉字典+提交请求体完整+后端404如实呈现)/ + 回执页 全链路 crash=0、方向无闪屏;平板端布局与交互(4 搜索条+分单内嵌展开+底部 5 元素操作栏) + 与改造前逐项一致 - 「出港计重」5.5 寸手机端适配(首个全链路 4+1 页模块,设计稿 03_出港计重): 待计重列表(三格统计 总票数/待计重/计重中 + 卡片状态标签 未计重/计重中 + 卡片内单票「提前运抵」+ FAB 进计重记录 + 筛选弹层 通道号/承运人/运单类型/代理人)、开始计重(头部预配统计卡 + PhoneFormRow 表单, diff --git a/CLAUDE.md b/CLAUDE.md index 9be348d..347b5f6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1110,6 +1110,18 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = isEditMode 复用为手机全屏「修改记录」覆层)+ 手机专属新页 `GjcWeighingWbDetailActivity`(运单详情)。 搜索分流规则(实测):含字母→fno、11 位数字→wbNo、其余→likeNo(likeNo 按 8 位 no 匹配并非模糊); checkIn 过滤等 7 项后端缺口见问题清单 #12~#18 + - 「出港运抵」主列表 + 3 个手机专属新页:`IntExpArriveActivity`(待运抵/已运抵 Tab,客户端按 + `declareStatus` 是否为空拆分数据集,卡片长按浮层:待运抵→补充、已运抵→重置+回执)、 + `IntExpArriveSubOrderActivity`(分单明细,数据直接复用主列表已加载的 `haWbList`,零新增请求)、 + `IntExpArriveReceiptActivity`(回执内容只读页,复用 `haWbList[].response`)、 + `IntExpArriveSupplementActivity`(补充信息,参照 Pad 端国际进港「收发货人信息」批量应用模式, + 后端接口不存在,实机 404 已确认,见问题清单 #19)。 + Tab 过滤两个坑:① **RecyclerView 里 `View.GONE` 不会让 item 塌陷为 0 高度**(不同于普通 + ViewGroup),必须在数据层整体 `refresh()` 过滤后的子集给 adapter,不能给 item 根节点加 + visibility 绑定(实机截图验证过,见「常见编译错误速查」);② 通过 `Intent.putExtra(Serializable)` + 传递的 `GjcHaWb`/`GjcMaWb`,其 `checked`/`showMore`/`actionMenuVisible` 字段标了 + `@Transient`(= JVM `transient`,Java 序列化会跳过),反序列化后为 null,直接 + `.checked.set(...)` 会崩溃——接收方 `initOnCreated` 必须对列表 `.map { it.copy() }` 补上 - ⏳ **待办**: - `PhoneSearchBar` 接入 AutoQuery 联想(`AutoQueryManager` 目前只对接了 Pad 系组件) - 出库交接 Tab 角标恒 0:`IntExpOutHandover/pageQueryTotal` 出参恒 0(后端缺陷,问题清单 #6), @@ -1202,6 +1214,8 @@ adb shell am start -n com.lukouguoji.aerologic/com.lukouguoji.gjc.activity.IntEx | 手机版筛选项默认值(如日期)自动被清空 | 多个复合自定义 View 内部子控件 id 相同,系统按 id 恢复状态时跨实例串档 | 组件重写 `dispatchSaveInstanceState`/`dispatchRestoreInstanceState` 为 `dispatchFreezeSelfOnly`/`dispatchThawSelfOnly`(见「手机版公共组件库」) | | 手机上页面先横屏再转竖屏(闪一下) | Manifest 写死 `screenOrientation="userLandscape"`,系统建窗口时已按横屏,代码纠正为时已晚 | 改成 `android:screenOrientation="unspecified"`,由 `BaseActivity` 按形态锁定(见「屏幕方向」小节) | | 平板先竖屏再转横屏 + 交互后 UI 放大约 1.6 倍 | Manifest 用了 `@integer/screen_orientation` 资源引用;系统解析 Manifest 不套用限定符,全部取到竖屏值,AutoSize 随之选了平板竖屏 720dp 基准 | Manifest 改回 `unspecified`(见「屏幕方向」小节的 ⛔ 说明) | +| Tab/分类切换后列表顶部留一大块空白,卡片数量却不对 | 给 item 根节点加了 `visibility="@{tab条件 ? VISIBLE : GONE}"`——RecyclerView/LinearLayoutManager 不会像普通 ViewGroup 那样让 GONE 的子项自动塌陷为 0 高度,仍按测量高度参与滚动区域计算 | 不要用 item 级 visibility 做过滤;在 ViewModel 里自行维护完整列表,Tab 切换时把过滤后的子集整体 `commonAdapter()?.refresh(filteredList)` 给 adapter | +| 通过 `Intent.putExtra(Serializable)` 传递的 Bean,切换其 `checked`/`showMore` 等状态时崩溃 `NullPointerException: ... on a null object reference` | 这些字段标了 `@Transient`(= JVM `transient`,本意是避免 Gson 网络请求序列化 `ObservableBoolean`),但 Java 对象序列化(Intent 传递走的机制)会跳过 `transient` 字段的恢复,反序列化后是 null | 接收方 `initOnCreated` 里对列表做 `.map { it.copy() }`——`.copy()` 会重新走一遍类体初始化逻辑,用全新 `ObservableBoolean(false)` 补上 | --- diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml index 3fabae5..a169c60 100644 --- a/app/src/debug/AndroidManifest.xml +++ b/app/src/debug/AndroidManifest.xml @@ -80,5 +80,29 @@ android:exported="true" tools:replace="android:exported" /> + + + + + + + + + + + + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cc1e1d7..c02e4dd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -145,6 +145,24 @@ android:configChanges="orientation|keyboardHidden" android:exported="false" android:screenOrientation="unspecified" /> + + + + + + +qP}nw$;ThPCw6lGqb*T|2SFuTFFUHew>xP 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 delta 10890 zcmZvCWl$x}vMuiJ?(Q(S4L-QLySw|wVSvHiox$DR-QC%^!{E-H@0_^r#yRo&PexW( zX0NE|?v<6b+R{L)LqHJ~WxydYKtMoXK)8N=#3S~?{x!O^C}qE%;+JUv?U&M}5_-%e z@+73Ju!D@!os0!m1%to0HWE{+!27^2aNcH)XAc}R-l=-!U!V> zpkZzUBtqD!URO7@93X~DcY@JxMK4ez87g{7U@0YgA!Ij2OzjFOQi&k70R8lByIZB# z=4lB5gm@RULODmh>sAE-z8F1l>|O}+dn#XSMaIFlS7!Gs5I)M0ywpV&gwxs#7pHK7 z?HnS5BRBLdXtb`uXL?KdAL01!Iq&W59Xo=x&7+ZYW6M%X4h@m1kUdp9)GG%5*hVJF z+ou(*)n4g$&L0EM46B?s$4u+Y|FIIf>AG3uC=Fkr+)zmWtVkJ>9i zqCN~1K=0B4pDXbzr^grwCP7Rve>l;-?Br-QPbHtosj#K%mI?_~*^}zknikp!0+F_?^wM9ABnYD+=e);ZD zt`3hW7C8ray|Wv$LsI=*^KxTm_ujE9!=uCWwQC^H6oWhqO8jb0)19-;bhKwQWbX9_ zFmK)DC&q&3B;lbkKhAtP1`>8$Jn!1JtufTRT-#=3u7!P^Iyb%V044ZcG!ZVeIn#Bn zjd8?~##f$8vu*w_)RLfd!+8O`ZAfD=3-D{D)ua-X z(HO_Gi)JQMwy7HwoQ##LzaV>L;^;|}n9VcS7N{!@Q;jLBkNdgc0bsKzN35m%HuC{bc|tcA&j2_v<<)eEU4*O4r;8aaW!IBnCJQ~HD1xtNnGim;r*fD zBa;x}r70xO#XrU0j8IsIIDO{jD`-uWvEORWNA;hcud>JQn*x2 zPr8?ORttK&KFg^jR-?}^H)Hxn!mskDV_^OMOw$36Mm^Yy3NKzZaT4CaJ@50|iMkAT zlI!~AcYA(ku(pFzg<>lQKmo|oBGQ%IyY75=zxpV}Akeo3K3;biJ#Z8yILnk4*~hn; z>Z818P3VyK>}P~f znU?X8w&>mP8o@|ExISu3OLiV1%U!FLUU{zF8qYnXh9U&)1)ce`! zrUOGsoWkbwW9;6wMRaU)zO>LZC8By*qP2{J2y0>^5gz>D45?B@ED&chqdZ1l{}~3_ z5vL{nyWk*;4Dy z-`oC89Qllv0Miiv9wPOg$!cg0T6u3IaRj9hPAbA4dza>C&ynh^9ig~i;c3ro>0A^Z zo5f(6&|>ZJAq6ch+T8#3GHAEPQlg4l`r?R6zv+-wQ{B%0g*j2+HX(AbL?) z=DI*tGH|R6Be%{$Rg$4g#=)u1KvW){z*HWckRfIF0V&rsJ%MZsEudsN&9^9x%@>$kpF_`Ml$?mRkaBuu0jtIM-_T{mn3^@^pG3rO>#d>uLs z^vmZvJ=;h_zfS~ATCPZ==NrX*EtVOVo;^=O9%K<^0zffRgx9+-Id)I{wgbbU%^NJ{ z3YE0J0lG(@b9CF3jbx|#JUGXdoLpKoqh|;~5tc{~%aTg49gQ=(*#hDk)rcEu^bc`P zF5x6tNcA}+lJmdWg<)XZ6reDaHL+WYgX&gu7tW=ERW9_Av(EUr zmx#F4khqtgRP(Gve*`Yocw}lcWWtv$s0&YyPm={{VXRbb0`pAiie>ToSi64e-A&Z_ zw$6h!M9Z9n)Kb2r>3G96J<7Nu52bP51pb2On4^aeRP#=u(!{+WWIb1UjND1hTqA?9 z1Ms{?>+Ae5W1-n=GNZj*e_M_SU;BNe3VH{@f%DO+Ev+El9&#gQK4(+;@w0v49*1 zr$@Igt|zvsO!lCWs|S=$P>2z3P~b0U;4g6C)OWD{hKAAB?B4SEIOiY5L3AH}?&=YD z*+>N@h(l2P^tsR!H>ku2&HO%e1PG^95Mc$kTInU=@k!uT$wv7_EHufIoP?9jsL;5L zX6s`9C3?#r_4K>_NAZFJ#amAN9RO9XB#RDInvjzhR!R{KJxFS)Tb9rdz4pGaFPh&f zW$4rx?KzGTk^7@2O_xq8FpSH)g(52XER_%=59**`9=631+33rNrNAK`EX^WXMz(T17b5Du8e5k~4z% z+&$!oIGZ7~%Sr;?`aBCR^iI=ZNmir{ime9Bi(oUPu;~b1!!nEJNL-K2u1>GlT;_^_ z%d70v<>j0Vw22H?a6j7O*(Q478TdzZT9ivwO}Q~PQ8!9q1o>IMXKr4kT>aiXPA%nk zL9<0wL??UYObE6TF)AFKiU(}5d!jCnYTpn*W~p?VXpY|Q#v7?AQbjor^rIUs(3S?c zb2M{$LV&R|E}d3j*1{g(xmGoHlXcTH@RK4$3MbHO2l^kCSdV&JJ(_nFX{9&o*Bg_l zKqT!RL-J7sl?a^DP!=D>WXdZUz(2Fn)d45jCKAFsGnxmhrzh<9^Z^z0s}{9?f8_CC z$QECx`-He(^;-!_!t`nc5hXfMA*6bn3(?XVrirwoy2TxqI?_?z3u)%@UeC*+G)=f_ zN^$yypGocNR(80zPxDgj7o$7b>?x~ag=50Tu~;5a@FcFYsh~~Ks8A!@RDTQJv~-u8 z(_8UBqSvpxvgm68Re;7zrT%6IfsJlA+c(ZO+?^gTrxSt{{#WKzAKC7&!#v(WTDGL6$#)GVL2JlH#-_c-e-T~RnTA+M- zkCJTNulT^mWz5jkiw;$W^*|f{{zfB^0Pv*c8%i)H19v)|Yf{ zVFI&p3qs>vEg_Tlme4&ULGDfyW`NrEpO;2#-{7Uix@-L3ypOUm0eGg@h7Vkq}NsOlA zW|e2a6&e7h7S>+W>I4*=nJSm`$c*v4msA`YWk^8@gC3DOI-khs=9gs21aS}3aQ>8( zNdplfvxk%~5#+v18UWf%h-&?0CCeCp-Ca;!Z{fRL1svOT8E<~03*a(OmL6D2RyvN> zfW{gk4@HR2=A1frcPMey4wx@-z0jZ0JfXsY&$eK2jj5XzsH}@4x(bYjq-NcyH5BIi zc4$htNV{)zJ7(aV2P+}zofr3~jsySE)VJukj%%Nsn)CH$y8e%-#1HqPv^i38Fdp35 z@J_Z&5P)x!a)`dpxBQV{@@w{So;a2Mp;cSL1D+cWIHMyBWoYrD!~)%$$N>Bd^23S? z{pP_6P3CL$V^IL%Do#O#7&T47aOpdJpF~4i;70=zz3U!(?15CYW7;UVVZf7TeE?qnERf8~t=jBkC z^rw|73ngkiA}N0PG77rmw4`AR6H0?Y$EkwHT?>71VhK{xcIG~IKIKwtLAzc!Xl<+S zl*eSHF5vRx`Y{@JUTUi*nKGKt$4V_NVVdvKVq*6lpfyh(JxZ<6XmK zJ|FI{Zk<0hx_3z}xV?*m^QxUiZZBV!96v|Krr^zSJ|+}X5-AQhUJjWj0FX!y5~_)A zkz!}pRcs+5P{J9=%eYC|$|jX6jEOVbfEy^aX?Z+eQN=XO283%}1p#Xk-qtb`GGQ7v z^+~Z`%$y*c_T@5c$wLv^mxx8LU4g0@GFEYa%b7q7g`Z;u7(Js^r9Y75wO05+6wQV= z5X&}Il=_q6P{`Be`UfM0ayVmq)0(h|Tk&+51^}&`P`$0QV(cF>AkAXEvjsHhSsy(0yFcnxe^g6t&m`A6l}c+>1-3 zCgs1z^O7_4FUg}jOfg5L^w~{DMA5-H>k|Za8?Nvs=S=9nD@vEk65ThKRpZwq*Sf(% z-dU2u)}4wLW4I?aip1F30=B%Es+R%IrN05Gq~ec^GhRZ+**Q--)U}(yV?+ zODi`UGyg4Hwe$oeqD!Qw8Y^4mkd-K;n5~<(>on18P(kg!^%p}7rQ`NOLV(|3?0Brg z$Ba->&EH+jh}0ul2jIQV$?N1OvPg^iT~&r-c4j)v|L9@P9*9EF5_A(K*`!IRktqZb zN@ntO($<151gy}ODqoPhu}S1DjwdedL*6nJ|KaG$%)uy@v@3tIY0ROV0sV4Cfg^JP zwx^;~tk;!o>f#M@WGK6+e`>235wpvnMOwj&A}Uw9;imZg1ZaV>2`XTTc$;M+2{hZD zv2^*GRu;vh-{^Fz_o0biqbNOGqx#3_Zn2_ySr_L=tNqrbH)aje%&+t zX5*e_x zIhc*se_X2g+|jdaNd@0XRvL5ivSvWGMA)gjv-_~rJ)ud3H#Wq|npY>`Tt_075D zRkLjE6ri=X27o1}*)gA|tW1V-;?t=~#{s1IaqvYC{!Tk(xV?S2^O%uW$nARnGtltG z*}$Y^ftd>82T?XGUqI?ibQX=ukubx3z!D5ssrIgYKd-l@cY9Q(C1qK4 zbWZ5Q%(vVUt`AkH1V>`%9y)Rtwau*Y=8PN)%)8T~hCf(5Zi7IGKGYbjV9bGu8bf&L||)D9e*w@3Gnu3*gCv>E6HfgVC{>j$M5ZVkIX8;lsXsbP>kv;AQb*f zHFKcq$`>TlWF@8o-8SZ}QTJgIX6NYl4?yOCLwTgl%2BIB_zawpnj zI5Rf|ZEhv@^|f$XN*i~4qVTy*oeWnEyyT!nKYH|S1D|;W zvu}>aWNFAAQ!pO>;K~>7BtuV^R&C&$TP-`5hFmCXano0u7mrUKD)WQ+g=(@VuB?$S zS7%edtvkF*v$-FK7kye#etFIO?M=fxwVxJ+EUP)rPfwI>I-kiJ4hXg*2A$uV7sKhk z;KKv(r&BAUh`aq;;mB-a3Uo-$o8=S+e7R=L=i!SStGp*dbhJhH8!ec(bKVmi39nz+ z%04i%BY$3SnfBXoxXIIxRPUQ2VyWKd1)Z+-!GKLQ>)K#W@uNv7RheLMrU zsx)@5%0RX&g15MCEYG!vm>03CjV?`s+`&PcKw-JHuLLD8AAA7&! zlR6m~BZ$|e+KLUzQF=tth{a@=JQFnh}Dvs|??#u^g!i^>y!Xg9iF=qQwJVM4w6%I-D8wtt(#+ZnPw{v= z$Y4L%)`)3rm|nfpCwYak?^--ZpX`)gwizB0lz0%9{ZxJU!U0T`g7tn5_psUDx=Pg6 z)YwLejWuRv$FBa25jgIxz&FcHQeAsh9j%m1s^3H=J;QLCM1B{1VM~J7>YH_s9&1s_ zZVOniIFw;jq68nCm#h!P3)&F&VUYQ_Uu%{!^DLWumQG&gcM#Oy92n1SVw~f+0Q*YZ%d?fXD)9B>7(`cKR8e(CB=sCGrV0`=X2+Tv1k%= z@G=y!mCIK42UQb%3(t{83*a5|Rpg;*$*lEb%wx!+3txv}lIV8ry`TKV41cAZR~YSP zqnIn?I@X+B+CEtMH!xuhP?8hBR#zcMVzR#kFlQcC-SD|jr({muYQNuEr|BWk`-8rH zIJa&7W~Rjdns9yy_Z(jM0{_n=9pyEL&tFg=Aa2Qm7f&yr6#B6Y)d|-+|Mq*i# z>5EB6uE0}dLTHhs+Hs~@RLO1hk0;R2IW-&X02R4>%+_Etuop0R27u|n8w6%|aW8|a zM$Usb-ieB`7B=&{$)}1n>6*kdtGYR!Xog7VY@Cx6nV$6|-t@v*-aDS+aRX|rD?R<) zmdxARg4GO$DZqoARQaWMb`mnPtNKL=(Om{I@xtNwD)Q&y5S7-Mj-8-`z4XaTRf<>p zvR5(|5AB2TnSjMiby_VL_r6TIhuZb`I-NH9NS}?i90h?ht)(_9H{*dRUv`(O?hBgj^W@(#E;x)&p0H}N{%#C&cF-*t^gcxIh{-12K)~eK>QcTR_#y_O_@Eg~@ zNBp`QSOmzp;FGnKgv?dW_1C zjoBOm(lFFX$)J5(Hen!q)P?cM@K@*EMBEj&FktwCPV)(b_(64Ys%BTLD=Cz9l7 zaSF+n_$Im8%!$BBOwbrhktl?;8coH%Fx*L4$$p05X{$L18t&m|K)3+%T|g*~-?$bf z2?IbWN6LbO`<($gayf7ho7+*>LVXe~vnA}Ei-~8C30LVfV6Yo}a)+`^>h6#lpAC`D zU3sywKN}qt!E2xZFD4(Skp}8}V1dp%cjP{A!^?v&OrH}i0^_MjA{#Iv5aE?n;{2K| zh7X1JCWFFQlwbri5lNQn#*!Tu{UIiRS_g1*!2CBNyJF9!c;abH8$Gu&(uiV2jbNir z4wsc^TF_Z(EA}-!MPi=t5k_FX#7+{gQGAnnL<3FNxEqT-1l|b3X34n9UpO!3Tz9G5 zo-q)&-%Hom@TpGmFlm5eAS@R<+fgyHu{a+UCuQrd{Pou+fA%{s$#Az`_Ww&Rm)VQfY2(YzVJcXg}QMD)RyC`=KR_@*~&yNC{0-?6nAQfIG zYgFu1f&f$)4=1NG6l!1sOcBtM8Nj&VwAXbDv+W(@4g&w{RfJ7_u4v*9wQ!71-2S(M zd+TD0r}+i4`>Xuk;e8%Pw7q+h005o@hwZ`3OjV*+dd{O!TsH-vA6j+?S4F zqzn=RcLxVu=NEpq@|7sdaLw(f0UD?-y1KClzKGj33t(3(b7pT~V`0(cu!W5XhL6RN z3iS}hzm8XV@*UMHZlyl1?X=VTc&&96V)uW?ksm98sbq@}K&H~yf|R!kCb6IFh-qSS z2CQoY_q4S8-fRGJ;Sx;+_5fZ1^)B5qb)(j_$ps^IAqP09iY)DUv1M>n5M(Bk-@49H zvafN8`xfsSR+nIhHez%!GgE(D6{7Rb@?D)Q67(>-~GzB4cMM+A9%&wiD~~#CEKVD2R|@n-7!rdDvj{oK1`?(EN<`+_mF!fJZMJz!x7N# zi)0%rQ2na#`d20Jsz~R2&);jZ?fo1su$p{&VQRL?PcN*NALi#KEq;9|YG_(7nV;== z`uInnh|?|&g#J`|NEnbBlX=6IojyY~RbDD|)J=u#VU^+s=5K+{|25!LN~@UH6Jh43 za{U_oWO1!^PSSDJKtUGK!8|l79|A`R=Ckt=__MLPAas{N6xNsCJ7E`!3zd2mM~R6O zukxap-+S)0%R|N|zf)%1EJK500Ujh)5HVknaf`3=Jk2<`CXDrp6z8kjm2IUs8)QGK zfJJVkJEocWGW84eKbec(jab9?FLO;}{=-}i%dAoVRwdZI1aTlhgMc9a!)U~R+01@} z`!AdILB6I$JjrB3jF!+e_m+%4*1uJ*$})&Gch=80GJiZ0BGLX-CZN`0h*T{RQ~qW# zorQaLkZ*tGPJg_9G19(%A#YL9ywyE%w`F{|JapB%-HyoLR+i~D*I(N<<*_l0DWlt1 z?JN;7z9Qb1o}InhRdIAt)a?MMaNe)Zu=VKC$DW$m(N+7NHGNXq@u#g*ujy05-@TsE zehYiWe?y;xW&BMq<#653-K=X2&%=e6uk?Dl>=E8^*r3>Fm9ppC^|+hf&P(6O;c2vI zlZEvo&sL$?`Fv5=l_CgY*9 zsd0Jy3iQAxOz`g!*Soy=x*(k_PMWMA`lzm2apFj;W#R&Azeh+O7?E~A_|0KiP|JP9 zaeUI+9s}}DOTTeU?3x`87rqzU?OMT}uQ#+f;3O|j?sNlHE#Wk%DC<7qOipWb;nFvc z!|;!4QfPqJ_~kb|hgpCDH7WB+U7`tw$|0Tvy02*3KGj>M>gfKu67`WLcmITz-Sie_ zgI;3K#f~BG7M%8C;Xds)O&hJ+ahS$1^ar?eBiS42^xl^cMWVQ*Pr-)B zJ>P!FwP1D&Wppu3Wxknk{Ak>e6qkM$F${Hx)>%WUw)+{{eF(s@O}V2<@6I$Sl7u#} z2IU);@$X_uVt%CdIEq%1lfIwP4TfaLbQuAwEROR#*t)Zes{N?ot2lK<%Ve2Eb&7+2 zC)uR`EDYF;}EtBYNivy%7yaC0MXdi_EaysE9iB{?z185ry_v}Z` zVHQE%=joQ@E6?G*4THZ|4Kei5T2S}|AI1aKS<7}rw+)@A#uh76s;C=`%BiXA)-s;`wmBi%9+ccZ@V zYZTNXws%OW^E?EXRH55gWES9CS6)hN3R4vK}3WyCV8Wwn2#gpcX z*pY~Y_#sNlxOe`Jd@KI@ew(RX-d>h(w-y>}*=`W5hc@)DW;) z`}C*MWpSB8DSsNw6iAHC{)`W9m5SB5jy?RnU|6&Kv#UD+VkH(4f&yVUjV$3(g|J4zX8yoWonLqS-DW)yZpDstdMZ|Dw^wWZ@`)*_-HnY4 z`T2mNi=`nyUE>_aRaZ;#Q=ooQpacP`-yj3;_5(uToRUen^oZmM9i)ksge#ea=1MYD z9^}CII_ufo`!j)<6NRM!IBd}(|0xPp`gFP?uX8|AAdwpg?gym-`ewdep~8b5be^c( zAj~=mTHW^){?>6Ca-VV4h?DYFhV$#{mw5nI)kH!80ut~_@xW6O$~?z?H8)&e`Z14A zO6lj;l&MUzYZ7!}>I?c^?o;*4OOt&R-G&NSXhPh@0S7DYt1+DcZsOe~r_2EbXVgb4 z`i3Tca3YsX?^okSRJm0}7R~zVOU;lQj1GSp3sR20o<5EpW7|8HZGBl~mur{ucnyF! zh(#V3XTlREp^k9g8{;UhUx6@)q>}dG2i+0yf&zSC@|+Z4YB=V^+`HO8@>9*13ckB-B$Q{l{|*sVx;K}Mb%Jr=Ynk$SJgW27K(n)@>8t7WJ!|p18nFD9UysczS9gaIqiELnyMn)_CDhkNPJVkY< z8~S*ME$_+*2xcoE5?U&-8o$00RogU&#rUlT!;o4AUt52U+yB%?Loqr|fGM6a*D<2W zPp4XA+XL!TD^M}c_f$3vm583sW_AmNFoq~4s>~N8KNK!F9y?YvcxH+^YTmr4AKwDm z7^@4jUJ9wHF`8Z0d9U`?YoW618qTHHV9?vA?!C)wx9oPc6LJLy z|10WC#1=dH$JUEaf&R;%m3a8aHjMtz`1b&r6yN{pArsA|IR7;*R|+5WG_ga9jO0I+ zfgm6_e}$C)dj$m2!6f#vVzRO_dD_`3%7B7lfd45>Sb%@^8dq{8reb6`*$ij7zhabe}sPVBr3|_{u`qVKG+Fw;!hdEf4OCU f-B$j@9SH*D|AL(O=kKjrfxjCON+_7`|D^jLqRs0U diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt index e05c916..fb47c05 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt @@ -1,6 +1,7 @@ package com.lukouguoji.module_base.bean import androidx.databinding.ObservableBoolean +import java.io.Serializable import java.text.SimpleDateFormat import java.util.Date import java.util.Locale @@ -122,12 +123,31 @@ data class GjcMaWb( val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态 @Transient val showMore: ObservableBoolean = ObservableBoolean(false) // 展开状态 + @Transient + val actionMenuVisible: ObservableBoolean = ObservableBoolean(false) // 5.5寸手机版:卡片长按操作浮层显隐 // 兼容现有API的isSelected属性 var isSelected: Boolean get() = checked.get() set(value) = checked.set(value) + /** + * 5.5寸手机版:是否处于「待运抵」Tab(申报状态为空)。 + * 接口无按申报状态区分的查询参数,Tab 由客户端对已加载数据拆分。 + */ + val isPending: Boolean + get() = declareStatus.isNullOrEmpty() + + /** + * 5.5寸手机版:申报状态三色标签的着色分类(01=绿/W=靛蓝/其余非空=琥珀)。 + */ + val declareTagColor: String + get() = when (declareStatus) { + "01" -> "green" + "W" -> "indigo" + else -> if (declareStatus.isNullOrEmpty()) "" else "amber" + } + // ==================== 状态转换扩展属性 ==================== /** * 计重状态中文 @@ -277,15 +297,36 @@ data class GjcHaWb( var tallyOpId: String? = null, // 理货操作人ID var declareCount: Long? = null, // 申报次数 var activeId: Long? = null // 活动ID -) { +) : Serializable { // ==================== UI扩展字段 ==================== @Transient val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态 + @Transient + val actionMenuVisible: ObservableBoolean = ObservableBoolean(false) // 5.5寸手机版:卡片长按操作浮层显隐 // 兼容现有API的isSelected属性 var isSelected: Boolean get() = checked.get() set(value) = checked.set(value) + + /** + * 5.5寸手机版:申报状态三色标签的着色分类(01=绿/W=靛蓝/其余非空=琥珀)。 + * 与 GjcMaWb.declareTagColor 同源逻辑,作用于分单自身的 arrivalStatus。 + */ + val haWbTagColor: String + get() = when (arrivalStatus) { + "01" -> "green" + "W" -> "indigo" + else -> if (arrivalStatus.isNullOrEmpty()) "" else "amber" + } + + /** + * 5.5寸手机版「回执」页:运抵操作时间(格式化)。 + */ + val arrivalOpDateText: String + get() = arrivalOpDate?.let { + SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(it) + } ?: "" } /** diff --git a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt index b17d31f..284433f 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt @@ -851,6 +851,16 @@ interface Api { @POST("IntExpArrive/deleteDeclare") suspend fun deleteArriveDeclare(@Body data: RequestBody): BaseResultBean + /** + * 国际出港运抵-分单补充收发货人信息(5.5寸手机版新增) + * + * 后端暂无此接口(api-doc 搜索 IntExpArrive、HaWb 均无匹配),路径为参照 Pad 端国际进港 + * IntImpAirManifest/complete 命名习惯拟定的建议值,见 documents/后端接口对接问题清单.xlsx。 + * 请求体为分单数组,仅需 haWbId 与收发货人相关字段。 + */ + @POST("IntExpArrive/haWb/supplement") + suspend fun supplementArriveHaWb(@Body data: RequestBody): BaseResultBean + /** * 国际出港移库-分页查询 * 接口路径: /IntExpMove/pageQuery diff --git a/module_base/src/main/res/drawable/bg_phone_fab_amber.xml b/module_base/src/main/res/drawable/bg_phone_fab_amber.xml new file mode 100644 index 0000000..7d921e1 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_fab_amber.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_fab_green.xml b/module_base/src/main/res/drawable/bg_phone_fab_green.xml new file mode 100644 index 0000000..cc2e7b6 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_fab_green.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_fab_purple.xml b/module_base/src/main/res/drawable/bg_phone_fab_purple.xml new file mode 100644 index 0000000..15aa096 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_fab_purple.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_tag_amber.xml b/module_base/src/main/res/drawable/bg_phone_tag_amber.xml new file mode 100644 index 0000000..abb4e6a --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_tag_amber.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_tag_indigo.xml b/module_base/src/main/res/drawable/bg_phone_tag_indigo.xml new file mode 100644 index 0000000..8979188 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_tag_indigo.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/module_base/src/main/res/values/colors.xml b/module_base/src/main/res/values/colors.xml index 8247886..074da37 100644 --- a/module_base/src/main/res/values/colors.xml +++ b/module_base/src/main/res/values/colors.xml @@ -75,5 +75,9 @@ #EA580C #FEE2E2 #DC2626 + #E0E7FF + #6366F1 + #FEF3C7 + #D97706 \ No newline at end of file diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveActivity.kt index a1ab477..ce5498f 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveActivity.kt @@ -3,6 +3,7 @@ package com.lukouguoji.gjc.activity import android.app.Activity import android.content.Intent import android.os.Bundle +import androidx.databinding.ObservableBoolean import com.alibaba.android.arouter.facade.annotation.Autowired import com.alibaba.android.arouter.facade.annotation.Route import com.alibaba.android.arouter.launcher.ARouter @@ -10,15 +11,24 @@ import com.lukouguoji.gjc.R import com.lukouguoji.gjc.databinding.ActivityIntExpArriveBinding import com.lukouguoji.gjc.viewModel.IntExpArriveViewModel import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.GjcHaWb +import com.lukouguoji.module_base.bean.GjcMaWb import com.lukouguoji.module_base.common.Constant import com.lukouguoji.module_base.common.ConstantEvent import com.lukouguoji.module_base.impl.FlowBus import com.lukouguoji.module_base.impl.observe import com.lukouguoji.module_base.ktx.addOnItemClickListener +import com.lukouguoji.module_base.ktx.commonAdapter import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil +import java.util.ArrayList /** * 国际出港-出港运抵页面 + * + * 布局 id 不区分设备,平板/手机由资源限定符自动选择: + * layout-sw600dp/activity_int_exp_arrive.xml(平板) + * layout/activity_int_exp_arrive.xml(手机) */ @Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE) class IntExpArriveActivity : @@ -31,12 +41,25 @@ class IntExpArriveActivity : override fun layoutId() = R.layout.activity_int_exp_arrive override fun viewModelClass() = IntExpArriveViewModel::class.java + /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ + val filterPanelVisible = ObservableBoolean(false) + + /** 供 [com.lukouguoji.gjc.holder.IntExpArriveViewHolder] 绑定 item 布局的 viewModel 变量(父类 viewModel 为 protected) */ + val itemViewModel: IntExpArriveViewModel get() = viewModel + override fun initOnCreate(savedInstanceState: Bundle?) { // 注入 ARouter 参数 ARouter.getInstance().inject(this) setBackArrow("国际出港运抵") binding.viewModel = viewModel + binding.activity = this + + // 手机版专属数据:加载「代理」筛选下拉 + // 平板端不调用,查询链路与请求次数与改造前完全一致 + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } // 如果有传入运单号,自动填充并触发搜索 if (!wbNoParam.isNullOrEmpty()) { @@ -63,6 +86,77 @@ class IntExpArriveActivity : } } + // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 字段与数据) ==================== + + /** + * 手机版 Tab 切换回调:PhoneStatusTab 已通过双向绑定写入 viewModel.currentTab, + * 这里触发 ViewModel 把适配器数据集替换为过滤后的子集(不发起新请求)。 + */ + fun onArriveTabChanged() { + viewModel.onTabChangedPhone() + } + + /** 卡片长按:展开操作浮层(View.OnLongClickListener 要求返回 Boolean) */ + fun showCardActionPhone(bean: GjcMaWb): Boolean { + bean.actionMenuVisible.set(true) + return true + } + + /** 点击浮层遮罩/空白处:收起操作浮层 */ + fun hideCardActionPhone(bean: GjcMaWb) { + bean.actionMenuVisible.set(false) + } + + /** 选择圈勾选状态变化后回调(由 ViewHolder 调用) */ + fun onItemCheckChanged() { + viewModel.onItemCheckChanged() + } + + /** 手机版筛选弹层显隐切换 */ + fun toggleFilterPanel() { + filterPanelVisible.set(!filterPanelVisible.get()) + } + + /** 手机版筛选:重置 */ + fun resetFilter() { + viewModel.flightDate.value = "" + viewModel.flightNo.value = "" + viewModel.agentCodePhone.value = "" + } + + /** 手机版筛选:确认 */ + fun confirmFilter() { + filterPanelVisible.set(false) + viewModel.searchClick() + } + + /** + * 进入「分单明细」页:直接传递该运单已加载的 haWbList,零新增请求。 + */ + fun openSubOrder(bean: GjcMaWb) { + val list = ArrayList(bean.haWbList.orEmpty()) + IntExpArriveSubOrderActivity.start(this, bean.wbNo.orEmpty(), list) + } + + /** + * 进入「回执」页(手机专属只读页):复用 haWbList[].response + arrivalOpDate,零新增请求。 + */ + fun openReceipt(bean: GjcMaWb) { + bean.actionMenuVisible.set(false) + val list = ArrayList(bean.haWbList.orEmpty()) + IntExpArriveReceiptActivity.start(this, bean.wbNo.orEmpty(), list) + } + + /** + * 进入「补充信息」页(手机专属新页):对该运单整个 haWbList 批量应用(参照 Pad 端国际进港 + * IntArrSupplementInfoViewModel 的批量复制模式)。后端暂无保存接口,见接口问题清单。 + */ + fun openSupplement(bean: GjcMaWb) { + bean.actionMenuVisible.set(false) + val list = ArrayList(bean.haWbList.orEmpty()) + IntExpArriveSupplementActivity.start(this, bean.wbNo.orEmpty(), list) + } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (requestCode) { diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveReceiptActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveReceiptActivity.kt new file mode 100644 index 0000000..1571b25 --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveReceiptActivity.kt @@ -0,0 +1,43 @@ +package com.lukouguoji.gjc.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityIntExpArriveReceiptBinding +import com.lukouguoji.gjc.viewModel.IntExpArriveReceiptViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.GjcHaWb +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.ktx.refresh + +/** + * 国际出港运抵-回执内容页(5.5寸手机版专属只读新页,平板端无对应页面) + * + * 数据来自主列表页已加载的 haWbList,零新增请求。 + * 对应设计稿 documents/5.5寸手持端设计文件/04_出港运抵/receipt.html。 + */ +class IntExpArriveReceiptActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_exp_arrive_receipt + override fun viewModelClass() = IntExpArriveReceiptViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("回执内容") + binding.viewModel = viewModel + + viewModel.initOnCreated(intent) + viewModel.receiptList.observe(this) { binding.rv.refresh(it) } + } + + companion object { + @JvmStatic + fun start(context: Context, wbNo: String, haWbList: ArrayList) { + val starter = Intent(context, IntExpArriveReceiptActivity::class.java) + .putExtra(Constant.Key.CODE, wbNo) + .putExtra(Constant.Key.DATA, haWbList) + context.startActivity(starter) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSubOrderActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSubOrderActivity.kt new file mode 100644 index 0000000..3e2259d --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSubOrderActivity.kt @@ -0,0 +1,92 @@ +package com.lukouguoji.gjc.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.databinding.ObservableBoolean +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityIntExpArriveSubOrderBinding +import com.lukouguoji.gjc.viewModel.IntExpArriveSubOrderViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.GjcHaWb +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.ktx.commonAdapter +import com.lukouguoji.module_base.ktx.refresh + +/** + * 国际出港运抵-分单明细页(5.5寸手机版专属新页,平板端无对应页面) + * + * 数据来自主列表页已加载的 haWbList(Intent 传入),零新增请求。 + * 对应设计稿 documents/5.5寸手持端设计文件/04_出港运抵/suborder.html。 + */ +class IntExpArriveSubOrderActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_exp_arrive_sub_order + override fun viewModelClass() = IntExpArriveSubOrderViewModel::class.java + + /** 筛选弹层显隐(仅 UI 状态) */ + val filterPanelVisible = ObservableBoolean(false) + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("分单明细") + binding.viewModel = viewModel + binding.activity = this + + viewModel.initOnCreated(intent) + + // 监听数据变化刷新列表 + viewModel.displayList.observe(this) { binding.rv.refresh(it) } + } + + /** 子项选中状态变化后回调(由 ViewHolder 调用) */ + fun onItemCheckChanged() { + viewModel.onItemCheckChanged() + } + + /** 全选按钮点击:切换全部选中状态后强制刷新列表(checked 为原地修改,不触发 LiveData) */ + fun checkAllClick() { + viewModel.checkAllClick() + binding.rv.commonAdapter()?.notifyDataSetChanged() + } + + /** 卡片长按:展开操作浮层(View.OnLongClickListener 要求返回 Boolean) */ + fun showActionMenu(bean: GjcHaWb): Boolean { + bean.actionMenuVisible.set(true) + return true + } + + /** 点击浮层遮罩:收起操作浮层 */ + fun hideActionMenu(bean: GjcHaWb) { + bean.actionMenuVisible.set(false) + } + + /** 长按菜单「重置」(单条) */ + fun resetSingleClick(bean: GjcHaWb) { + bean.actionMenuVisible.set(false) + viewModel.resetSingleClick(bean) + } + + fun toggleFilterPanel() { + filterPanelVisible.set(!filterPanelVisible.get()) + } + + fun resetFilter() { + viewModel.hnoFilter.value = "" + } + + fun confirmFilter() { + filterPanelVisible.set(false) + viewModel.searchClick() + } + + companion object { + @JvmStatic + fun start(context: Context, wbNo: String, haWbList: ArrayList) { + val starter = Intent(context, IntExpArriveSubOrderActivity::class.java) + .putExtra(IntExpArriveSubOrderViewModel.KEY_WB_NO, wbNo) + .putExtra(Constant.Key.DATA, haWbList) + context.startActivity(starter) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSupplementActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSupplementActivity.kt new file mode 100644 index 0000000..1d510b2 --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSupplementActivity.kt @@ -0,0 +1,41 @@ +package com.lukouguoji.gjc.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityIntExpArriveSupplementBinding +import com.lukouguoji.gjc.viewModel.IntExpArriveSupplementViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.GjcHaWb +import com.lukouguoji.module_base.common.Constant + +/** + * 国际出港运抵-补充信息页(5.5寸手机版专属新页,平板端无对应页面) + * + * 参照 Pad 端国际进港「收发货人信息」补充页的批量应用模式:对该运单整个 haWbList 批量应用 + * 同一份收发货人表单。后端暂无保存接口,见 IntExpArriveSupplementViewModel 顶部注释。 + * 对应设计稿 documents/5.5寸手持端设计文件/04_出港运抵/supplement.html。 + */ +class IntExpArriveSupplementActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_exp_arrive_supplement + override fun viewModelClass() = IntExpArriveSupplementViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("补充信息") + binding.viewModel = viewModel + viewModel.initOnCreated(intent) + } + + companion object { + @JvmStatic + fun start(context: Context, wbNo: String, haWbList: ArrayList) { + val starter = Intent(context, IntExpArriveSupplementActivity::class.java) + .putExtra(Constant.Key.CODE, wbNo) + .putExtra(Constant.Key.DATA, haWbList) + context.startActivity(starter) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveReceiptViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveReceiptViewHolder.kt new file mode 100644 index 0000000..d757114 --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveReceiptViewHolder.kt @@ -0,0 +1,19 @@ +package com.lukouguoji.gjc.holder + +import android.view.View +import com.lukouguoji.gjc.databinding.ItemIntExpArriveReceiptBinding +import com.lukouguoji.module_base.base.BaseViewHolder +import com.lukouguoji.module_base.bean.GjcHaWb + +/** + * 国际出港运抵-回执内容列表 ViewHolder(5.5寸手机版专属只读页) + */ +class IntExpArriveReceiptViewHolder(view: View) : + BaseViewHolder(view) { + + override fun onBind(item: Any?, position: Int) { + val bean = getItemBean(item) ?: return + binding.bean = bean + binding.executePendingBindings() + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveSubOrderViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveSubOrderViewHolder.kt new file mode 100644 index 0000000..ca6450e --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveSubOrderViewHolder.kt @@ -0,0 +1,32 @@ +package com.lukouguoji.gjc.holder + +import android.view.View +import com.lukouguoji.gjc.activity.IntExpArriveSubOrderActivity +import com.lukouguoji.gjc.databinding.ItemIntExpArriveSubOrderBinding +import com.lukouguoji.module_base.base.BaseViewHolder +import com.lukouguoji.module_base.bean.GjcHaWb + +/** + * 国际出港运抵-分单明细列表 ViewHolder(5.5寸手机版专属页面) + * + * 选中状态变化只影响本页自身的 ViewModel(不复用全局 FlowBus.EVENT_CHECK_CHANGED, + * 避免与主列表页共享同一事件、产生跨页面的无意义联动)。 + */ +class IntExpArriveSubOrderViewHolder(view: View) : + BaseViewHolder(view) { + + override fun onBind(item: Any?, position: Int) { + val bean = getItemBean(item) ?: return + val activity = itemView.context as? IntExpArriveSubOrderActivity + binding.bean = bean + binding.activity = activity + binding.executePendingBindings() + + // 整卡点击切换选择状态 + binding.ll.setOnClickListener { + bean.checked.set(!bean.checked.get()) + activity?.onItemCheckChanged() + binding.executePendingBindings() + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveViewHolder.kt index 6c2750a..963cb75 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpArriveViewHolder.kt @@ -2,6 +2,7 @@ package com.lukouguoji.gjc.holder import android.view.View import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.activity.IntExpArriveActivity import com.lukouguoji.gjc.databinding.ItemIntExpArriveBinding import com.lukouguoji.module_base.adapter.setCommonAdapter import com.lukouguoji.module_base.base.BaseViewHolder @@ -12,52 +13,73 @@ import com.lukouguoji.module_base.ktx.refresh /** * 国际出港-出港运抵 列表项ViewHolder + * + * item 布局分平板(layout-sw600dp/item_int_exp_arrive.xml,内嵌分单子列表 rv_sub 展开/收起) + * 与手机(layout/item_int_exp_arrive.xml,分单改为独立「分单明细」页,无 rv_sub/iv_show 等 id) + * 两个变体,单侧独有的 id 在 Binding 基类中为 `@Nullable`,需判空调用。 */ class IntExpArriveViewHolder(view: View) : BaseViewHolder(view) { override fun onBind(item: Any?, position: Int) { val bean = getItemBean(item) ?: return + val activity = itemView.context as? IntExpArriveActivity binding.bean = bean binding.position = position + binding.activity = activity + binding.viewModel = activity?.itemViewModel 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()) } + // 选择圈点击事件(手机独有,仅待运抵 Tab 可见) + binding.ivSelect?.setOnClickListener { + bean.checked.set(!bean.checked.get()) + activity?.onItemCheckChanged() + binding.executePendingBindings() + } + + // 子列表 RecyclerView 仅平板存在,手机版分单改走独立页面 + val rvSub = binding.rvSub ?: return + // 初始化子列表 RecyclerView setCommonAdapter( - binding.rvSub, + rvSub, IntExpArriveSubViewHolder::class.java, R.layout.item_int_exp_arrive_sub ) // 刷新子列表数据 val subList = bean.haWbList ?: emptyList() - binding.rvSub.refresh(subList) + rvSub.refresh(subList) updateSubListVisibility(subList.isNotEmpty()) } private fun updateSubListVisibility(hasData: Boolean) { + val llHeader = binding.llHeader ?: return + val dividerHeader = binding.dividerHeader ?: return + val rvSub = binding.rvSub ?: return + val tvEmpty = binding.tvEmpty ?: return if (hasData) { - binding.llHeader.visibility = View.VISIBLE - binding.dividerHeader.visibility = View.VISIBLE - binding.rvSub.visibility = View.VISIBLE - binding.tvEmpty.visibility = View.GONE + llHeader.visibility = View.VISIBLE + dividerHeader.visibility = View.VISIBLE + rvSub.visibility = View.VISIBLE + 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 + llHeader.visibility = View.GONE + dividerHeader.visibility = View.GONE + rvSub.visibility = View.GONE + tvEmpty.visibility = View.VISIBLE } } } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveReceiptViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveReceiptViewModel.kt new file mode 100644 index 0000000..f303f50 --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveReceiptViewModel.kt @@ -0,0 +1,34 @@ +package com.lukouguoji.gjc.viewModel + +import android.content.Intent +import androidx.lifecycle.MutableLiveData +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.holder.IntExpArriveReceiptViewHolder +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.GjcHaWb +import com.lukouguoji.module_base.common.Constant + +/** + * 国际出港运抵-回执内容 ViewModel(5.5寸手机版专属只读页) + * + * 数据直接复用主列表页已加载的 haWbList.response / arrivalOpDate 字段,无需任何新增请求。 + * 对应设计稿 documents/5.5寸手持端设计文件/04_出港运抵/receipt.html。 + */ +class IntExpArriveReceiptViewModel : BaseViewModel() { + + val receiptList = MutableLiveData>(emptyList()) + + // 适配器配置 + val itemViewHolder = IntExpArriveReceiptViewHolder::class.java + val itemLayoutId = R.layout.item_int_exp_arrive_receipt + + @Suppress("UNCHECKED_CAST") + fun initOnCreated(intent: Intent) { + val list = intent.getSerializableExtra(Constant.Key.DATA) as? ArrayList + // .copy() 补上被 Java 序列化跳过的 @Transient 字段(checked 等),见分单明细页同款注释 + receiptList.value = (list ?: emptyList()) + .map { it.copy() } + .filter { !it.response.isNullOrEmpty() } + .sortedByDescending { it.arrivalOpDate } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveSubOrderViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveSubOrderViewModel.kt new file mode 100644 index 0000000..1c564e6 --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveSubOrderViewModel.kt @@ -0,0 +1,137 @@ +package com.lukouguoji.gjc.viewModel + +import android.content.Intent +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.dialog.IntExpArriveResetDialogModel +import com.lukouguoji.gjc.holder.IntExpArriveSubOrderViewHolder +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.GjcHaWb +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.common.ConstantEvent +import com.lukouguoji.module_base.http.net.NetApply +import com.lukouguoji.module_base.impl.FlowBus +import com.lukouguoji.module_base.ktx.launchLoadingCollect +import com.lukouguoji.module_base.ktx.showToast +import com.lukouguoji.module_base.ktx.toRequestBody +import kotlinx.coroutines.launch + +/** + * 国际出港运抵-分单明细 ViewModel(5.5寸手机版专属页面) + * + * 数据直接复用主列表页已加载的 haWbList(Intent 传入),无需任何新增请求。 + * 筛选仅「分单号」在客户端生效——航班日期/航班号/代理等字段在单个运单的分单集合内 + * 恒为同一值,筛选它们没有实际意义(设计稿疑似沿用主列表筛选组件模板,未按此页场景定制)。 + */ +class IntExpArriveSubOrderViewModel : BaseViewModel() { + + // 运单号(页面标题辅助展示,非必需) + var wbNo: String = "" + private set + + // 完整分单列表(Intent 传入,不随筛选变化) + private var fullList: List = emptyList() + + // 当前展示列表(按分单号筛选后的结果) + val displayList = MutableLiveData>(emptyList()) + + // 筛选:分单号(客户端 contains 匹配) + val hnoFilter = MutableLiveData("") + + // 全选状态与已选计数 + val isAllChecked = MutableLiveData(false) + val selectedCount = MutableLiveData("0") + + // 适配器配置 + val itemViewHolder = IntExpArriveSubOrderViewHolder::class.java + val itemLayoutId = R.layout.item_int_exp_arrive_sub_order + + @Suppress("UNCHECKED_CAST") + fun initOnCreated(intent: Intent) { + wbNo = intent.getStringExtra(KEY_WB_NO).orEmpty() + val list = intent.getSerializableExtra(Constant.Key.DATA) as? ArrayList + // Java 序列化会跳过 checked/actionMenuVisible(标了 @Transient,即 JVM transient 修饰符), + // 反序列化后这两个 ObservableBoolean 字段为 null。.copy() 会重新走一遍类体初始化逻辑, + // 用全新的 ObservableBoolean(false) 补上,避免全选/长按时 NPE(已实机崩溃验证过)。 + fullList = (list ?: emptyList()).map { it.copy() } + displayList.value = fullList + } + + /** + * 分单号筛选(客户端 contains 匹配,非后端查询)。 + */ + fun searchClick() { + val key = hnoFilter.value?.trim().orEmpty() + displayList.value = if (key.isEmpty()) { + fullList + } else { + fullList.filter { it.hno?.contains(key, ignoreCase = true) == true } + } + updateCheckAllStatus() + } + + fun onItemCheckChanged() { + updateCheckAllStatus() + } + + fun updateCheckAllStatus() { + val list = displayList.value ?: return + isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() } + selectedCount.value = list.count { it.checked.get() }.toString() + } + + fun checkAllClick() { + val list = displayList.value ?: return + val shouldCheckAll = !isAllChecked.value!! + list.forEach { it.checked.set(shouldCheckAll) } + isAllChecked.value = shouldCheckAll + selectedCount.value = if (shouldCheckAll) list.size.toString() else "0" + } + + /** + * 长按菜单「重置」(单条分单)。 + */ + fun resetSingleClick(bean: GjcHaWb) { + val dialog = IntExpArriveResetDialogModel { dialogModel -> + val params = mutableMapOf("haWbList" to listOf(bean)) + if (dialogModel.resetStatusCode != null) { + params["restStatus"] = dialogModel.resetStatusCode + } + launchLoadingCollect({ NetApply.api.resetArriveDeclare(params.toRequestBody()) }) { + onSuccess = { + showToast("状态重置成功,请返回列表页下拉刷新查看最新状态") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + } + } + } + dialog.show() + } + + /** + * 底部「申报」:批量申报当前选中的分单。 + */ + fun declareClick() { + val selected = displayList.value?.filter { it.isSelected } ?: emptyList() + if (selected.isEmpty()) { + showToast("请选择要申报的分单") + return + } + val params = mapOf("haWbList" to selected).toRequestBody() + launchLoadingCollect({ NetApply.api.arriveDeclare(params) }) { + onSuccess = { + showToast("运抵申报成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + getTopActivity().finish() + } + } + } + + companion object { + const val KEY_WB_NO = "wbNo" + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveSupplementViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveSupplementViewModel.kt new file mode 100644 index 0000000..eff362a --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveSupplementViewModel.kt @@ -0,0 +1,119 @@ +package com.lukouguoji.gjc.viewModel + +import android.content.Intent +import androidx.lifecycle.MutableLiveData +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.GjcHaWb +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.http.net.NetApply +import com.lukouguoji.module_base.ktx.launchCollect +import com.lukouguoji.module_base.ktx.launchLoadingCollect +import com.lukouguoji.module_base.ktx.showToast +import com.lukouguoji.module_base.ktx.toRequestBody +import com.lukouguoji.module_base.ktx.verifyNullOrEmpty +import dev.utils.app.info.KeyValue + +/** + * 国际出港运抵-补充信息 ViewModel(5.5寸手机版专属新页) + * + * 参照 Pad 端国际进港 [com.lukouguoji.gjj.viewModel.IntArrSupplementInfoViewModel] 的 + * 「单一表单批量复制到选中列表」模式:对该运单的整个 haWbList 批量应用同一份收发货人信息。 + * + * ⚠️ 后端暂无保存接口,见 [com.lukouguoji.module_base.http.net.Api.supplementArriveHaWb] 注释 + * 与 documents/后端接口对接问题清单.xlsx。 + */ +class IntExpArriveSupplementViewModel : BaseViewModel() { + + // 表单编辑用数据对象(取首个分单填充,让用户看到已有数据) + val dataBean = MutableLiveData(GjcHaWb()) + + // 批量应用的目标分单列表 + private var haWbList: List = emptyList() + + // 国家代码下拉列表 + val countryCodeList = MutableLiveData>(emptyList()) + + // 通讯方式下拉列表 + val comTypeList = MutableLiveData>(emptyList()) + + @Suppress("UNCHECKED_CAST") + fun initOnCreated(intent: Intent) { + val list = intent.getSerializableExtra(Constant.Key.DATA) as? ArrayList + // .copy() 补上被 Java 序列化跳过的 @Transient 字段(checked 等),见分单明细页同款注释 + haWbList = (list ?: emptyList()).map { it.copy() } + dataBean.value = haWbList.firstOrNull()?.copy() ?: GjcHaWb() + + loadCountryCodeList() + loadComTypeList() + } + + private fun loadCountryCodeList() { + launchCollect({ NetApply.api.getCountryCodeList() }) { + onSuccess = { result -> + countryCodeList.value = result.data?.mapNotNull { bean -> + if (bean.code != null && bean.name != null) KeyValue(bean.name, bean.code) else null + } ?: emptyList() + } + } + } + + private fun loadComTypeList() { + launchCollect({ NetApply.api.getCommunicateTypeList() }) { + onSuccess = { result -> + comTypeList.value = result.data?.mapNotNull { bean -> + if (bean.code != null && bean.name != null) KeyValue(bean.name, bean.code) else null + } ?: emptyList() + } + } + } + + fun cancel() { + getTopActivity().finish() + } + + /** + * 保存按钮点击 - 将表单信息复制到该运单的所有分单,批量提交。 + */ + fun save() { + val formBean = dataBean.value ?: return + + if (formBean.consigneeName.verifyNullOrEmpty("收货人名称不能为空")) return + if (formBean.consigneeCountryCode.verifyNullOrEmpty("收货人国家代码不能为空")) return + if (formBean.consigneeComType.verifyNullOrEmpty("收货人通讯方式不能为空")) return + if (formBean.consigneePnum.verifyNullOrEmpty("收货人联系号码不能为空")) return + if (formBean.consignorName.verifyNullOrEmpty("发货人名称不能为空")) return + if (formBean.consignorCountryCode.verifyNullOrEmpty("发货人国家代码不能为空")) return + if (formBean.consignorComType.verifyNullOrEmpty("发货人通讯方式不能为空")) return + if (formBean.consignorPnum.verifyNullOrEmpty("发货人联系号码不能为空")) return + + if (haWbList.isEmpty()) { + showToast("无可保存的分单数据") + return + } + + val updatedList = haWbList.map { haWb -> + haWb.copy( + consigneeName = formBean.consigneeName, + consigneeCountryCode = formBean.consigneeCountryCode, + consigneeComType = formBean.consigneeComType, + consigneePnum = formBean.consigneePnum, + consigneeAddress = formBean.consigneeAddress, + consignorName = formBean.consignorName, + consignorCountryCode = formBean.consignorCountryCode, + consignorComType = formBean.consignorComType, + consignorPnum = formBean.consignorPnum, + consignorAddress = formBean.consignorAddress + ) + } + + launchLoadingCollect({ NetApply.api.supplementArriveHaWb(updatedList.toRequestBody()) }) { + onSuccess = { + showToast("保存成功") + getTopActivity().finish() + } + onFailed = { code, msg -> + showToast("保存失败:$msg(后端接口暂未支持,见接口问题清单)") + } + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt index 663daf9..4693b2f 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt @@ -20,6 +20,7 @@ import com.lukouguoji.module_base.ktx.launchLoadingCollect import com.lukouguoji.module_base.ktx.showToast import com.lukouguoji.module_base.ktx.toRequestBody import com.lukouguoji.module_base.model.ScanModel +import dev.utils.app.info.KeyValue import dev.utils.common.DateUtils import com.lukouguoji.module_base.ktx.formatDate import kotlinx.coroutines.launch @@ -45,6 +46,7 @@ class IntExpArriveViewModel : BasePageViewModel() { fun onItemCheckChanged() { updateCheckAllStatus() + updateCheckAllStatusPhone() } fun updateCheckAllStatus() { @@ -52,6 +54,101 @@ class IntExpArriveViewModel : BasePageViewModel() { isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() } } + // ========== 5.5寸手机版专属(平板布局不引用,零影响) ========== + + /** 当前 Tab:"pending"(待运抵) / "shipped"(已运抵)。接口无申报状态查询参数,Tab 由客户端对已加载数据拆分 */ + val currentTab = MutableLiveData("pending") + + /** Tab 配置 */ + val arriveTabs = MutableLiveData( + listOf(KeyValue("待运抵", "pending"), KeyValue("已运抵", "shipped")) + ) + + /** 两个 Tab 的角标计数(当前已加载数据的客户端统计,非全量,见接口问题清单) */ + val arriveTabCounts = MutableLiveData(listOf("", "")) + + /** 手机版全选状态(仅统计待运抵 Tab 内的项,与 Pad 端 [isAllChecked] 统计口径不同) */ + val isAllCheckedPhone = MutableLiveData(false) + + /** 手机版已选数量(底部操作条「已选 N 项」) */ + val selectedCountPhone = MutableLiveData("0") + + /** 手机版筛选弹层「代理」(后端 pageQuery 支持 agentCode 入参,复用既有 agentCode 语义查询) */ + val agentCodePhone = MutableLiveData("") + val agentListPhone = MutableLiveData>(emptyList()) + + private var phoneExtrasEnabled = false + + /** + * 完整已加载列表(跨分页累计,未按 Tab 过滤)。 + * + * ⚠️ RecyclerView/LinearLayoutManager 不会像普通 ViewGroup 那样让 `View.GONE` 的子项 + * 自动塌陷为 0 高度——它仍按子项的测量高度参与滚动区域计算,导致"隐藏"的卡片在列表里 + * 留下一段空白(已实机截图验证)。因此 Tab 切换不能靠给 item 加 visibility 绑定, + * 必须真正地把适配器的数据集替换成过滤后的子集([applyTabFilterPhone])。 + */ + private var allLoadedList: List = emptyList() + + /** + * 开启手机版专属数据:加载「代理」筛选下拉。仅由手机形态的 Activity 调用。 + */ + fun initPhoneExtras() { + phoneExtrasEnabled = true + launchCollect({ NetApply.api.getIntExpAgentList() }) { + onSuccess = { result -> + agentListPhone.postValue( + listOf(KeyValue("全部", "")) + (result.data ?: emptyList()).map { KeyValue(it.name ?: "", it.code ?: "") } + ) + } + } + } + + /** + * 手机版 Tab 切换:将适配器数据集替换为过滤后的子集(不重新请求)。 + * 由 Activity 在 [com.lukouguoji.module_base.ui.weight.phone.PhoneStatusTab] 的 + * 双向绑定写入 currentTab 后调用。 + */ + fun onTabChangedPhone() { + applyTabFilterPhone() + } + + private fun applyTabFilterPhone() { + val isPendingTab = currentTab.value == "pending" + val filtered = allLoadedList.filter { it.isPending == isPendingTab } + pageModel.rv?.commonAdapter()?.refresh(filtered) + updateCheckAllStatusPhone() + } + + /** + * 根据完整已加载列表重新计算 Tab 角标计数(每次数据变化后调用)。 + */ + private fun updatePhoneTabCounts() { + val pending = allLoadedList.count { it.isPending }.toString() + val shipped = allLoadedList.count { !it.isPending }.toString() + arriveTabCounts.value = listOf(pending, shipped) + } + + /** + * 手机版全选(适配器此时已只包含当前 Tab 的子集,待运抵 Tab 下即为全部可选项)。 + */ + fun checkAllClickPhone() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + val shouldCheckAll = !isAllCheckedPhone.value!! + list.forEach { it.checked.set(shouldCheckAll) } + isAllCheckedPhone.value = shouldCheckAll + updateCheckAllStatusPhone() + pageModel.rv?.commonAdapter()?.notifyDataSetChanged() + } + + /** + * 更新手机版全选状态与已选计数(基于适配器当前子集,即当前 Tab 的数据)。 + */ + fun updateCheckAllStatusPhone() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + isAllCheckedPhone.value = list.isNotEmpty() && list.all { it.checked.get() } + selectedCountPhone.value = list.count { it.checked.get() }.toString() + } + // ========== 全局展开状态 ========== /** * 全局展开状态 @@ -292,18 +389,53 @@ class IntExpArriveViewModel : BasePageViewModel() { } } + /** + * 手机版:卡片长按菜单「重置」(单条,已运抵 Tab 专用,对应设计稿长按浮层)。 + */ + fun resetSingleDeclareClick(bean: GjcMaWb) { + bean.actionMenuVisible.set(false) + + val dialog = IntExpArriveResetDialogModel { dialogModel -> + val params = mutableMapOf("maWbList" to listOf(bean)) + if (dialogModel.resetStatusCode != null) { + params["restStatus"] = dialogModel.resetStatusCode + } + launchLoadingCollect({ NetApply.api.resetArriveDeclare(params.toRequestBody()) }) { + onSuccess = { + showToast("状态重置成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + refresh() + } + } + } + dialog.show() + } + /** * 获取数据 (重写BasePageViewModel) */ override fun getData() { // 构建搜索条件 - val filterParams = mapOf( + val filterParams = mutableMapOf( "fdate" to flightDate.value?.ifEmpty { null }, "fno" to flightNo.value?.ifEmpty { null }, "wbNo" to waybillNo.value?.ifEmpty { null }, "hno" to hno.value?.ifEmpty { null } ) + // 手机版专属条件(平板 phoneExtrasEnabled 恒为 false,请求体与改造前完全一致) + if (phoneExtrasEnabled) { + // 搜索分流(与出港计重页一致):11 位数字精确匹配 wbNo,其余走 likeNo 模糊 + val key = waybillNo.value?.trim() ?: "" + if (key.isNotEmpty() && key.length != 11) { + filterParams["wbNo"] = null + filterParams["likeNo"] = key + } + filterParams["agentCode"] = agentCodePhone.value?.ifEmpty { null } + } + // 列表参数 (含分页) val listParams = (filterParams + mapOf( "pageNum" to pageModel.page, @@ -315,8 +447,21 @@ class IntExpArriveViewModel : BasePageViewModel() { // 获取列表 (带Loading) launchLoadingCollect({ NetApply.api.getIntExpArriveList(listParams) }) { - onSuccess = { - pageModel.handleListBean(it) { updateCheckAllStatus() } + onSuccess = { result -> + // 手机版:自行维护完整累计列表(不依赖 adapter.items 的历史状态,见 allLoadedList 注释) + if (phoneExtrasEnabled) { + val newPageItems = result.list ?: emptyList() + allLoadedList = if (pageModel.page <= 1) newPageItems else allLoadedList + newPageItems + } + + pageModel.handleListBean(result) { + updateCheckAllStatus() + if (phoneExtrasEnabled) { + // 用完整列表强制覆盖 adapter 数据集为当前 Tab 的过滤子集 + applyTabFilterPhone() + updatePhoneTabCounts() + } + } // 数据加载完成后,重置全局展开状态为收起 isAllExpanded.value = false } diff --git a/module_gjc/src/main/res/layout-sw600dp/activity_int_exp_arrive.xml b/module_gjc/src/main/res/layout-sw600dp/activity_int_exp_arrive.xml new file mode 100644 index 0000000..c88ab26 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/activity_int_exp_arrive.xml @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/item_int_exp_arrive.xml b/module_gjc/src/main/res/layout-sw600dp/item_int_exp_arrive.xml new file mode 100644 index 0000000..1a6b1af --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/item_int_exp_arrive.xml @@ -0,0 +1,520 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml b/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml index 8d05466..e6523c7 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml @@ -1,239 +1,161 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_int_exp_arrive_receipt.xml b/module_gjc/src/main/res/layout/activity_int_exp_arrive_receipt.xml new file mode 100644 index 0000000..f9d7624 --- /dev/null +++ b/module_gjc/src/main/res/layout/activity_int_exp_arrive_receipt.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_int_exp_arrive_sub_order.xml b/module_gjc/src/main/res/layout/activity_int_exp_arrive_sub_order.xml new file mode 100644 index 0000000..4e4b534 --- /dev/null +++ b/module_gjc/src/main/res/layout/activity_int_exp_arrive_sub_order.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_int_exp_arrive_supplement.xml b/module_gjc/src/main/res/layout/activity_int_exp_arrive_supplement.xml new file mode 100644 index 0000000..32bc29e --- /dev/null +++ b/module_gjc/src/main/res/layout/activity_int_exp_arrive_supplement.xml @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_int_exp_arrive.xml b/module_gjc/src/main/res/layout/item_int_exp_arrive.xml index 6b026ed..af4e1f8 100644 --- a/module_gjc/src/main/res/layout/item_int_exp_arrive.xml +++ b/module_gjc/src/main/res/layout/item_int_exp_arrive.xml @@ -1,511 +1,266 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_int_exp_arrive_receipt.xml b/module_gjc/src/main/res/layout/item_int_exp_arrive_receipt.xml new file mode 100644 index 0000000..b9b9915 --- /dev/null +++ b/module_gjc/src/main/res/layout/item_int_exp_arrive_receipt.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_int_exp_arrive_sub_order.xml b/module_gjc/src/main/res/layout/item_int_exp_arrive_sub_order.xml new file mode 100644 index 0000000..db52c92 --- /dev/null +++ b/module_gjc/src/main/res/layout/item_int_exp_arrive_sub_order.xml @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 15e7b15..77a6405 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 @@ -54,6 +54,12 @@ class GjViewModel : BaseViewModel() { Constant.AuthName.GjcCheckWeighing, ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_LIST ), + ActionBean( + "出港运抵", + R.drawable.img_gjc_chugang_diyun, + Constant.AuthName.GjcIntExpArrive, + ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE + ), // ULD管理属综合管理业务(Pad 端在「综合管理」菜单组),手机端首页暂无综合 Tab,挂在国际 Tab 下 ActionBean( "ULD管理", diff --git a/module_p/src/main/res/drawable-xxhdpi/img_gjc_chugang_diyun.png b/module_p/src/main/res/drawable-xxhdpi/img_gjc_chugang_diyun.png new file mode 100644 index 0000000000000000000000000000000000000000..430eb62ba7d680e5e1b8558ae63fc3af087a8f5f GIT binary patch literal 33013 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 r1*ec0B2BMeRKj{ Date: Thu, 30 Jul 2026 23:21:33 +0800 Subject: [PATCH 06/29] =?UTF-8?q?fix:=20=E5=87=BA=E6=B8=AF=E8=BF=90?= =?UTF-8?q?=E6=8A=B5=E6=89=8B=E6=9C=BA=E7=AB=AF=E5=AF=B9=E7=85=A7=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E7=A8=BFreview=E4=BF=AE=E6=AD=A3=E4=B8=8E=E9=87=8D?= =?UTF-8?q?=E7=BD=AE=E5=BC=B9=E6=A1=86=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 状态重置弹框改手机底部弹层:dialog 布局同名双变体(Pad 移 layout-sw600dp), 弹出位置按形态切 DIALOG_TYPE_BOTTOM/CENTER,为弹框适配首例 - 主列表补空态(文案按 Tab 切换)、回执页补「暂无回执内容」兜底 - 分单明细长按浮层按设计稿补「回执」按钮;底部统计加分母「已选 N / M 项」 - Tab 角标初始显示 0 - PhoneStatusTab/PhoneFilterPanel 补 dispatchSave/RestoreInstanceState 状态屏蔽(历史遗漏) - 双端实机验证:手机端各修正点与设计稿一致且 crash=0;平板端列表与批量重置弹框回归无变化 Co-Authored-By: Claude Fable 5 --- .../phone-adapt/references/pad-safety.md | 20 ++++ CHANGELOG.md | 12 ++ CLAUDE.md | 11 +- .../ui/weight/phone/PhoneFilterPanel.kt | 14 +++ .../ui/weight/phone/PhoneStatusTab.kt | 14 +++ .../activity/IntExpArriveSubOrderActivity.kt | 6 + .../dialog/IntExpArriveResetDialogModel.kt | 8 +- .../gjc/viewModel/IntExpArriveViewModel.kt | 8 +- .../dialog_int_exp_arrive_reset.xml | 87 ++++++++++++++ .../res/layout/activity_int_exp_arrive.xml | 56 +++++++-- .../activity_int_exp_arrive_receipt.xml | 57 +++++++-- .../activity_int_exp_arrive_sub_order.xml | 2 +- .../layout/dialog_int_exp_arrive_reset.xml | 111 ++++++++---------- .../layout/item_int_exp_arrive_sub_order.xml | 43 +++++-- 14 files changed, 348 insertions(+), 101 deletions(-) create mode 100644 module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_arrive_reset.xml diff --git a/.claude/skills/phone-adapt/references/pad-safety.md b/.claude/skills/phone-adapt/references/pad-safety.md index 5c30f26..69b8c26 100644 --- a/.claude/skills/phone-adapt/references/pad-safety.md +++ b/.claude/skills/phone-adapt/references/pad-safety.md @@ -44,6 +44,26 @@ com/lukouguoji/gjc/databinding/ItemXxxBinding.java `activity_xxx_phone.xml` 会生成 `ActivityXxxPhoneBinding`,而字段声明的类型是 `ActivityXxxBinding`。泛型擦除让**编译期查不出来**,一进页面就 `ClassCastException`。 +### 弹框(BaseDialogModel)也要双变体,最容易漏 + +页面布局适配完,长按/批量操作弹出的 DialogModel 仍会以 Pad 居中样式出现在手机上 +(出港运抵的「状态重置」就漏过)。做法与页面完全同构: + +1. dialog 布局 `git mv` 到 `layout-sw600dp/`,`layout/` 下写同名手机版(设计稿通常是底部弹层: + `bg_phone_panel_top` + 居中标题 + `ic_phone_close` + 全宽 `bg_phone_btn_primary` 确定键) +2. 弹出位置在构造参数按形态切换(XPopup 位置与布局是两回事,都要改): + +```kotlin +class XxxDialogModel(...) : BaseDialogModel( + if (DeviceUtil.isPhone()) DIALOG_TYPE_BOTTOM else DIALOG_TYPE_CENTER +) +``` + +3. 两变体 `` 一致(imports 不要求一致) + +参考:`IntExpArriveResetDialogModel` + `dialog_int_exp_arrive_reset.xml` 双变体。 +**适配收尾时逐个 grep 该页 ViewModel 里 `DialogModel(` 的调用点**,每个弹框都过一遍。 + ## 业务层零破坏的三个模式 ### 新增查询维度:默认空值 + 仅非空进请求 diff --git a/CHANGELOG.md b/CHANGELOG.md index 73ea40e..ae283ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,12 @@ - 新增手机版资源:`bg_phone_tag_indigo`/`bg_phone_tag_amber`(申报状态三色标签)、 `bg_phone_fab_purple`/`bg_phone_fab_amber`/`bg_phone_fab_green`(长按浮层圆形操作按钮) - 后端缺口 2 项登记问题清单 #19~#20(分单补充信息保存接口不存在、Tab 无申报状态查询参数) +- 「出港运抵」对照设计稿 review 修正:状态重置弹框手机端改为设计稿底部弹层 + (**弹框适配首个先例**:`dialog_int_exp_arrive_reset.xml` 同名布局双变体,Pad 版移至 + `layout-sw600dp/`,`IntExpArriveResetDialogModel` 构造参数按 `DeviceUtil.isPhone()` 切 + `DIALOG_TYPE_BOTTOM`/`CENTER`);主列表补空态(图标 + 文案按 Tab 切换「暂无待/已运抵的运单」); + 回执页补空态兜底「暂无回执内容」(单分单入口常无回执,避免纯白屏);分单明细长按浮层按设计稿 + 补「回执」按钮(单分单跳回执页);分单页底部统计加分母「已选 N / M 项」;Tab 角标初始显示 0 ### 修复 (Fixed) - **RecyclerView + Tab 过滤新坑**:给 item 根节点加 `visibility="@{...}"` 切 Tab 会在列表里 @@ -33,12 +39,18 @@ 修饰符,Java 序列化(Intent 传递机制)会跳过其恢复,反序列化后为 null,切换选中状态时 NullPointerException 崩溃。修复:接收方 `initOnCreated` 对列表 `.map { it.copy() }` 重新 触发类体初始化补上(已实机崩溃复现并验证修复) +- `PhoneStatusTab`/`PhoneFilterPanel` 补上遗漏的 `dispatchSaveInstanceState`/ + `dispatchRestoreInstanceState` 屏蔽覆写(其余 5 个手机版复合组件均已重写,这两个是历史遗漏; + 同页多实例时子控件状态可能按 id 跨实例串档) ### 验证 (Verified) - 出港运抵双端实机验证通过:手机端 Tab 切换(角标/卡片双向正确)/全选/单选/长按菜单/查看分单 /分单明细全选与长按重置/补充信息(真实数据回填+下拉字典+提交请求体完整+后端404如实呈现)/ 回执页 全链路 crash=0、方向无闪屏;平板端布局与交互(4 搜索条+分单内嵌展开+底部 5 元素操作栏) 与改造前逐项一致 +- 出港运抵 review 修正双端实机验证通过:手机端重置底部弹层(长按→重置→下拉展开选项)/主列表空态 + /回执页空态/分单浮层重置+回执双按钮/「已选 0 / 2 项」分母 全部与设计稿一致且 crash=0; + 平板端回归:列表、批量「状态重置」弹框仍为居中 Pad 样式,行为与改造前一致 - 「出港计重」5.5 寸手机端适配(首个全链路 4+1 页模块,设计稿 03_出港计重): 待计重列表(三格统计 总票数/待计重/计重中 + 卡片状态标签 未计重/计重中 + 卡片内单票「提前运抵」+ FAB 进计重记录 + 筛选弹层 通道号/承运人/运单类型/代理人)、开始计重(头部预配统计卡 + PhoneFormRow 表单, diff --git a/CLAUDE.md b/CLAUDE.md index 347b5f6..d8503b5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -975,7 +975,12 @@ Manifest 写死 `userLandscape` 时,即使 `BaseActivity` 在 `super.onCreate` 3. **Kotlin 侧不动**:`layoutId()`、`itemLayoutId`、ViewHolder 全部保持原样 4. **纯 UI 交互**(Tab 切换、弹层显隐)写在 Activity,不污染 ViewModel;状态过滤优先复用 ViewModel 既有字段 5. 手机布局顶部 `` 不变(变体自动切换) -6. **回到手机端首页加菜单入口**(最易遗忘,见下节)——不加的话页面在手机上根本进不去 +6. **弹框(BaseDialogModel)同样要适配**:dialog 布局照样走同名双变体(Pad 版移 `layout-sw600dp/`、 + 手机版在 `layout/` 写设计稿的底部弹层样式),弹出位置在构造参数按形态切换: + `BaseDialogModel(if (DeviceUtil.isPhone()) DIALOG_TYPE_BOTTOM else DIALOG_TYPE_CENTER)` + (参考 `IntExpArriveResetDialogModel` + `dialog_int_exp_arrive_reset.xml` 双变体)。 + 页面适配完要**逐个排查该页所有 DialogModel**,漏掉的会在手机上弹出 Pad 居中样式 +7. **回到手机端首页加菜单入口**(最易遗忘,见下节)——不加的话页面在手机上根本进不去 ### 手机端首页菜单入口(适配完必须加,否则没入口) @@ -1121,7 +1126,9 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = visibility 绑定(实机截图验证过,见「常见编译错误速查」);② 通过 `Intent.putExtra(Serializable)` 传递的 `GjcHaWb`/`GjcMaWb`,其 `checked`/`showMore`/`actionMenuVisible` 字段标了 `@Transient`(= JVM `transient`,Java 序列化会跳过),反序列化后为 null,直接 - `.checked.set(...)` 会崩溃——接收方 `initOnCreated` 必须对列表 `.map { it.copy() }` 补上 + `.checked.set(...)` 会崩溃——接收方 `initOnCreated` 必须对列表 `.map { it.copy() }` 补上。 + 2026-07-30 review 修正:状态重置弹框改手机底部弹层(弹框双变体首例,见改造步骤第 6 条)、 + 主列表/回执页补空态、分单浮层补「回执」、分单统计加分母、Tab 角标初始 0 - ⏳ **待办**: - `PhoneSearchBar` 接入 AutoQuery 联想(`AutoQueryManager` 目前只对接了 Pad 系组件) - 出库交接 Tab 角标恒 0:`IntExpOutHandover/pageQueryTotal` 出参恒 0(后端缺陷,问题清单 #6), diff --git a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFilterPanel.kt b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFilterPanel.kt index ba4c69e..f4c2b17 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFilterPanel.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneFilterPanel.kt @@ -1,7 +1,9 @@ package com.lukouguoji.module_base.ui.weight.phone import android.content.Context +import android.os.Parcelable import android.util.AttributeSet +import android.util.SparseArray import android.view.View import android.widget.FrameLayout import android.widget.ImageView @@ -42,6 +44,18 @@ class PhoneFilterPanel @JvmOverloads constructor( defStyleAttr: Int = 0 ) : FrameLayout(context, attrs, defStyleAttr) { + /** + * 同一页面可能出现多个含内部 id 的手机版复合组件,系统按 id 保存/恢复视图状态会跨实例串档。 + * 这里只保存/恢复自身状态、不下发给子控件;筛选值由 ViewModel + DataBinding 持有,无需视图级恢复。 + */ + override fun dispatchSaveInstanceState(container: SparseArray) { + dispatchFreezeSelfOnly(container) + } + + override fun dispatchRestoreInstanceState(container: SparseArray) { + dispatchThawSelfOnly(container) + } + val llPanel: LinearLayout val llContent: LinearLayout val tvTitle: TextView diff --git a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneStatusTab.kt b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneStatusTab.kt index b16b0b3..28dd2d0 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneStatusTab.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneStatusTab.kt @@ -1,7 +1,9 @@ package com.lukouguoji.module_base.ui.weight.phone import android.content.Context +import android.os.Parcelable import android.util.AttributeSet +import android.util.SparseArray import android.view.Gravity import android.view.View import android.widget.LinearLayout @@ -37,6 +39,18 @@ class PhoneStatusTab @JvmOverloads constructor( defStyleAttr: Int = 0 ) : LinearLayout(context, attrs, defStyleAttr) { + /** + * 同一页面可能出现多个含内部 id 的手机版复合组件,系统按 id 保存/恢复视图状态会跨实例串档。 + * 这里只保存/恢复自身状态、不下发给子控件;选中值由 ViewModel + DataBinding 持有,无需视图级恢复。 + */ + override fun dispatchSaveInstanceState(container: SparseArray) { + dispatchFreezeSelfOnly(container) + } + + override fun dispatchRestoreInstanceState(container: SparseArray) { + dispatchThawSelfOnly(container) + } + /** 双向绑定回调 */ var onChangeListener: InverseBindingListener? = null diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSubOrderActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSubOrderActivity.kt index 3e2259d..f67af53 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSubOrderActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSubOrderActivity.kt @@ -67,6 +67,12 @@ class IntExpArriveSubOrderActivity : viewModel.resetSingleClick(bean) } + /** 长按菜单「回执」(单条):复用回执只读页,仅传当前分单 */ + fun openReceipt(bean: GjcHaWb) { + bean.actionMenuVisible.set(false) + IntExpArriveReceiptActivity.start(this, viewModel.wbNo, arrayListOf(bean)) + } + fun toggleFilterPanel() { filterPanelVisible.set(!filterPanelVisible.get()) } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpArriveResetDialogModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpArriveResetDialogModel.kt index b18ae7c..3076ebf 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpArriveResetDialogModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/dialog/IntExpArriveResetDialogModel.kt @@ -6,14 +6,20 @@ import com.lukouguoji.gjc.R import com.lukouguoji.gjc.databinding.DialogIntExpArriveResetBinding 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/(居中弹框), + * 弹出位置随形态选择 BOTTOM/CENTER。 */ class IntExpArriveResetDialogModel( private val callback: (IntExpArriveResetDialogModel) -> Unit -) : BaseDialogModel(DIALOG_TYPE_CENTER) { +) : BaseDialogModel( + if (DeviceUtil.isPhone()) DIALOG_TYPE_BOTTOM else DIALOG_TYPE_CENTER +) { // 重置状态列表 val resetStatusList = MutableLiveData>() diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt index 4693b2f..4f52294 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt @@ -65,7 +65,11 @@ class IntExpArriveViewModel : BasePageViewModel() { ) /** 两个 Tab 的角标计数(当前已加载数据的客户端统计,非全量,见接口问题清单) */ - val arriveTabCounts = MutableLiveData(listOf("", "")) + val arriveTabCounts = MutableLiveData(listOf("0", "0")) + + /** 手机版空态(当前 Tab 过滤后无数据时显示,对应设计稿 empty-pending) */ + val emptyVisiblePhone = MutableLiveData(false) + val emptyTextPhone = MutableLiveData("暂无待运抵的运单") /** 手机版全选状态(仅统计待运抵 Tab 内的项,与 Pad 端 [isAllChecked] 统计口径不同) */ val isAllCheckedPhone = MutableLiveData(false) @@ -116,6 +120,8 @@ class IntExpArriveViewModel : BasePageViewModel() { val isPendingTab = currentTab.value == "pending" val filtered = allLoadedList.filter { it.isPending == isPendingTab } pageModel.rv?.commonAdapter()?.refresh(filtered) + emptyVisiblePhone.value = filtered.isEmpty() + emptyTextPhone.value = if (isPendingTab) "暂无待运抵的运单" else "暂无已运抵的运单" updateCheckAllStatusPhone() } diff --git a/module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_arrive_reset.xml b/module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_arrive_reset.xml new file mode 100644 index 0000000..de6675c --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/dialog_int_exp_arrive_reset.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml b/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml index e6523c7..c59a272 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml @@ -89,19 +89,51 @@ android:layout_height="0dp" android:layout_weight="1"> - + android:layout_height="match_parent"> + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_int_exp_arrive_receipt.xml b/module_gjc/src/main/res/layout/activity_int_exp_arrive_receipt.xml index f9d7624..772a63e 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_arrive_receipt.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_arrive_receipt.xml @@ -11,6 +11,8 @@ + + @@ -24,20 +26,51 @@ - + android:layout_weight="1"> + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_int_exp_arrive_sub_order.xml b/module_gjc/src/main/res/layout/activity_int_exp_arrive_sub_order.xml index 4e4b534..76c3559 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_arrive_sub_order.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_arrive_sub_order.xml @@ -82,7 +82,7 @@ android:layout_height="wrap_content" actionText='@{"申报"}' allChecked="@{viewModel.isAllChecked}" - countText='@{"已选 " + viewModel.selectedCount + " 项"}' + countText='@{"已选 " + viewModel.selectedCount + " / " + viewModel.displayList.size() + " 项"}' setOnActionClick="@{(v)-> viewModel.declareClick()}" setOnAllCheckClick="@{(v)-> activity.checkAllClick()}" /> diff --git a/module_gjc/src/main/res/layout/dialog_int_exp_arrive_reset.xml b/module_gjc/src/main/res/layout/dialog_int_exp_arrive_reset.xml index de6675c..53d390d 100644 --- a/module_gjc/src/main/res/layout/dialog_int_exp_arrive_reset.xml +++ b/module_gjc/src/main/res/layout/dialog_int_exp_arrive_reset.xml @@ -1,8 +1,16 @@ + - + + 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.resetStatusList}" + title='@{"状态"}' + type="@{PhoneDataLayoutType.SPINNER}" + value="@={model.selectedResetStatus}" /> - - - - - + + diff --git a/module_gjc/src/main/res/layout/item_int_exp_arrive_sub_order.xml b/module_gjc/src/main/res/layout/item_int_exp_arrive_sub_order.xml index db52c92..e421cdd 100644 --- a/module_gjc/src/main/res/layout/item_int_exp_arrive_sub_order.xml +++ b/module_gjc/src/main/res/layout/item_int_exp_arrive_sub_order.xml @@ -2,7 +2,7 @@ @@ -102,7 +102,7 @@ - + - + android:orientation="horizontal"> + + + + + + From 33c9f0e030fe6c1c7bcb80f79c782e5995214915 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 31 Jul 2026 18:13:44 +0800 Subject: [PATCH 07/29] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=87=BA?= =?UTF-8?q?=E6=B8=AF=E6=9F=A5=E8=AF=A2=E9=A1=B5=E9=9D=A25.5=E5=AF=B8?= =?UTF-8?q?=E6=89=8B=E6=9C=BA=E7=AB=AF=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 列表/详情/运单追踪三页同名布局双变体(平板移 layout-sw600dp/,Kotlin 零设备分支) - 列表:搜索行 + 三格统计(总票数/已入库/已离港,已加载数据客户端计数)+ 状态标签卡片 (已离港/已入库/未入库,前端按 fclose/opDate 推断)+ 9 项底部筛选弹层(特码改下拉) - 详情:3 Tab 复用 ViewPager2+Fragment,PhoneKvItem 网格;入库件数/重量按 warehouseList 求和 - 运单追踪:公共页 LogDetailActivity 双变体首例,手机竖排时间线动态构建,平板横向步骤条不动 - 修复 PhoneFilterPanel 筛选项超屏时底部按钮被挤出屏幕(内容插槽加 ScrollView) - PhoneKvItem 新增 tagColor 绿色高亮(海关放行),占位符不套标签底 - 手机首页国际 Tab 加出港查询入口;后端缺口 #21/#22 登记问题清单 - 双端实机验证通过(内网真实数据 + Proxyman Map Local 补验未入库兜底态) - skill 新增 references/proxyman.md:抓包/直调 A/B/Mock 与 api-doc 配合规范 Co-Authored-By: Claude Fable 5 --- .claude/skills/phone-adapt/SKILL.md | 17 +- .../skills/phone-adapt/references/api-doc.md | 8 + .../phone-adapt/references/components.md | 8 +- .../skills/phone-adapt/references/proxyman.md | 76 ++ CHANGELOG.md | 31 + CLAUDE.md | 14 +- app/src/debug/AndroidManifest.xml | 18 + .../page/log/detail/LogDetailActivity.kt | 107 ++- .../layout-sw600dp/activity_log_detail.xml | 231 ++++++ .../main/res/layout/activity_log_detail.xml | 271 ++---- documents/后端接口对接问题清单.xlsx | Bin 19513 -> 20336 bytes .../lukouguoji/module_base/bean/GjcMaWb.kt | 14 + .../ui/weight/phone/PhoneKvItem.kt | 20 +- .../ui/weight/phone/PhoneWidgetKtx.kt | 13 +- .../main/res/drawable/bg_phone_dot_blue.xml | 6 + .../main/res/drawable/bg_phone_dot_gray.xml | 6 + .../main/res/drawable/ic_phone_package.xml | 11 + .../src/main/res/drawable/ic_phone_tag.xml | 11 + .../res/layout/layout_phone_filter_panel.xml | 20 +- .../gjc/activity/GjcQueryActivity.kt | 36 +- .../gjc/viewModel/GjcQueryDetailsViewModel.kt | 50 ++ .../gjc/viewModel/GjcQueryViewModel.kt | 44 + .../res/layout-sw600dp/activity_gjc_query.xml | 237 ++++++ .../activity_gjc_query_details.xml | 125 +++ .../fragment_gjc_query_storage.xml | 137 ++++ .../fragment_gjc_query_warehouse.xml | 157 ++++ .../fragment_gjc_query_waybill.xml | 319 ++++++++ .../res/layout-sw600dp/item_gjc_query.xml | 318 ++++++++ .../layout-sw600dp/item_gjc_query_storage.xml | 99 +++ .../item_gjc_query_warehouse.xml | 119 +++ .../layout_gjc_query_filter.xml | 0 .../main/res/layout/activity_gjc_query.xml | 440 ++++++---- .../res/layout/activity_gjc_query_details.xml | 262 +++--- .../res/layout/fragment_gjc_query_storage.xml | 190 ++--- .../layout/fragment_gjc_query_warehouse.xml | 210 ++--- .../res/layout/fragment_gjc_query_waybill.xml | 771 ++++++++++-------- .../src/main/res/layout/item_gjc_query.xml | 490 +++++------ .../res/layout/item_gjc_query_storage.xml | 212 ++--- .../res/layout/item_gjc_query_warehouse.xml | 255 +++--- .../sixin/module_p/ui/enter/gj/GjViewModel.kt | 6 + .../res/drawable-xxhdpi/gjc_query_icon.png | Bin 0 -> 32301 bytes 41 files changed, 3730 insertions(+), 1629 deletions(-) create mode 100644 .claude/skills/phone-adapt/references/proxyman.md create mode 100644 app/src/main/res/layout-sw600dp/activity_log_detail.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_dot_blue.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_dot_gray.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_package.xml create mode 100644 module_base/src/main/res/drawable/ic_phone_tag.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/activity_gjc_query.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/activity_gjc_query_details.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/fragment_gjc_query_storage.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/fragment_gjc_query_warehouse.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/fragment_gjc_query_waybill.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/item_gjc_query.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/item_gjc_query_storage.xml create mode 100644 module_gjc/src/main/res/layout-sw600dp/item_gjc_query_warehouse.xml rename module_gjc/src/main/res/{layout => layout-sw600dp}/layout_gjc_query_filter.xml (100%) create mode 100644 module_p/src/main/res/drawable-xxhdpi/gjc_query_icon.png diff --git a/.claude/skills/phone-adapt/SKILL.md b/.claude/skills/phone-adapt/SKILL.md index 8a6fe6a..f2f520a 100644 --- a/.claude/skills/phone-adapt/SKILL.md +++ b/.claude/skills/phone-adapt/SKILL.md @@ -66,6 +66,10 @@ python3 $S/design_shots.py --html "…/出库交接.html" --out /tmp/design \ 返回同一批数据,一度误判为「后端不支持」;后查 api-doc 才发现正确参数名是 `handoverState`—— 后端对不认识的参数是**静默忽略**,不报错,实测只能证明「这个名字不对」,证不出「后端没这能力」。 +「参数是否真的生效」的 A/B 验证优先走 Proxyman MCP(`create_compose_http_from_flow` 复制 +真实请求改参重发,token 自动带上),分工与流程见 `references/proxyman.md`: +**api-doc 管契约(该有什么),Proxyman 管事实(实际发/回了什么)**。 + 核对完把结论落两处(模板与格式见 `references/api-doc.md`): - 后端真实缺口(缺入参/缺出参/数据不回填)→ 记入 `documents/后端接口对接问题清单.xlsx`, @@ -232,9 +236,12 @@ $P tap-text "已交接" # 按文字点击,比手算坐标可靠 $P texts # 用文字变化断言点击确实生效(如底部条应消失) $P shot /tmp/p1.png $P crash # 必须为 0 -$P req pageQuery # 核对请求体参数确实带上了新字段 ``` +核对请求/响应体优先用 Proxyman MCP(`filter_flows` + `get_flow_detail`,比 `req` 的 +logcat 抓包完整可靠;模拟器代理一行命令接入,见 `references/proxyman.md`); +Proxyman 不可用时兜底 `$P req pageQuery`。 + 逐项走查:列表/卡片两种形态、详情页、筛选弹层(重置+确认)、Tab 切换、单选与全选联动、 下拉真实取数、扫码入口。每步 `crash` 都要为 0。 @@ -253,7 +260,12 @@ $P req pageQuery # 核对请求体参数确实带上了新字段 **空值兜底**(真实数据空字段很常见——出库交接就出现过「库位」为空时橙色高亮标签只剩一个孤零零的 小色块,需要空值时不套标签底)。 -服务端当天没数据时(列表空)先放宽条件重查;仍为空就临时在 Activity 里注入样例 Bean 截图比对: +服务端当天没数据时(列表空)先放宽条件重查;仍为空、或要覆盖真实数据凑不出的形态 +(空字段、超长文本、罕见状态标签),**首选 Proxyman Map Local 造 mock**——零代码改动、 +零重构建,见 `references/proxyman.md` 场景 3(2026-07-31 出港查询用它一次验完 +已离港/已入库/未入库三种卡片形态)。验证完 `delete_rule` + 清模拟器代理。 + +Proxyman 不可用时才退回老办法:Activity 里临时注入样例 Bean 截图比对: ```kotlin // import com.lukouguoji.module_base.ktx.commonAdapter @@ -287,6 +299,7 @@ binding.rv.postDelayed({ ## 参考文件 - `references/api-doc.md` — api-doc MCP 连接与逐接口核对流程、后端缺口记录规范、已核对字段语义(阶段 2 前读) +- `references/proxyman.md` — Proxyman MCP 抓包/直调 A/B/Map Local mock 的接入与四个场景(阶段 2、5、6 用;与 api-doc 的分工:契约 vs 事实) - `references/components.md` — 7 个手机版公共组件的属性表、用法与封装新组件的规矩(写布局前读) - `references/pad-safety.md` — 布局变体约束、Pad 零破坏模式、易崩点(写代码前读) - `references/verification.md` — 双端 adb 命令、登录与直启、已知环境坑(验证前读) diff --git a/.claude/skills/phone-adapt/references/api-doc.md b/.claude/skills/phone-adapt/references/api-doc.md index 6570f2e..057ce55 100644 --- a/.claude/skills/phone-adapt/references/api-doc.md +++ b/.claude/skills/phone-adapt/references/api-doc.md @@ -77,6 +77,14 @@ curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \ 分单补充收发货人信息**后端完全没有对应接口**(`search_endpoints` 对 `IntExpArrive`/`HaWb` 关键字均搜不到分单更新接口,只有国际进港的 `IntImpAirManifest/complete`), 实机调用拟定路径 `IntExpArrive/haWb/supplement` 确认 404(缺口 #19) +- `IntExpSearch`(出港查询,2026-07-31 内网实测):查询入参 `outState`/`fno`/`dest`/`spCode`/`awbType`/ + `businessType`/`goodsCn`/`beginDate`/`endDate`/`agentCode`/`wbNo` 全部真实生效(平板既有口径); + 文档定义的 `isFclose`(筛选航班是否关闭)**pageQuery 与 pageQueryTotal 均静默忽略**(A/B 对照 + 全量 72 票与单日两组,加参前后结果完全一致,缺口 #21);`pageQueryTotal` 出参无已入库/已离港 + 分项计数(#21);`detail` 出参 Map 无 `lockStatus`(锁定状态)与计费重量字段(#22); + 详情「入库件数/入库重量」= `warehouseList` 各批次 pc/weight 求和(mock 与实测均吻合); + 卡片状态推断口径:`fclose` 非空=已离港、否则 `opDate` 非空=已入库; + 特码字典沿用 `DictUtils.getSpecialCodeList(flag=1, ieFlag="")`(ieFlag 必须空串) - `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/components.md b/.claude/skills/phone-adapt/references/components.md index bc747d4..75a4710 100644 --- a/.claude/skills/phone-adapt/references/components.md +++ b/.claude/skills/phone-adapt/references/components.md @@ -16,13 +16,17 @@ | `PhoneFilterPanel` | 底部筛选弹层(遮罩 + 面板 + 重置/确认) | `title`、`panelVisible`、`setOnResetClick`、`setOnConfirmClick`、`setOnDismissClick` | | `PhoneBottomBar` | 底部操作条(全选 + 已选统计 + 主按钮) | `allChecked`、`countText`、`actionText`、`setOnAllCheckClick`、`setOnActionClick` | | `PhoneStatBox` | 卡片内 2~4 列统计框,未传 label 的列自动隐藏 | `label1..4`、`value1..4` | -| `PhoneKvItem` | 详情页字段项(灰标签 + 数值) | `title`、`value`、`tag`(true → 橙色高亮标签) | +| `PhoneKvItem` | 详情页字段项(灰标签 + 数值) | `title`、`value`、`tag`(true → 高亮标签)、`tagColor`("orange" 默认 / "green" 放行正常态);占位符 "-"/"--" 不套标签底 | | `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}"` 切浅红删除按钮。 +`PhoneFilterPanel` 内容插槽已内置 ScrollView(2026-07-31 加):筛选项少时行为不变; +筛选项多到超屏(出港查询 9 项)时内容区收缩滚动,底部「重置/确认」按钮始终可见—— +此前无滚动时按钮会被挤出屏幕外且毫无报错,只表现为"点不到确认"。 + ⚠️ 两个已踩坑: - **FAB 盖住弹层**:浮动按钮带 elevation 时会浮在 `PhoneFilterPanel` 之上,弹层实例要加 `android:elevation="8dp"`(> FAB 的 6dp) @@ -129,6 +133,8 @@ android.util.Log.d("DBG", "value '$field' -> '$v'", Throwable("trace")) `ic_phone_chevron_right/down` `ic_phone_calendar` `ic_phone_close` `ic_phone_check_round_checked/unchecked`(圆形复选框) `ic_phone_clipboard`(剪贴板,白色 FAB 用)`ic_phone_weight`(砝码,可 tint) + `ic_phone_package`(件数)`ic_phone_tag`(特码/标签) +- 圆点:`bg_phone_dot_green/blue/gray`(状态指示点;蓝=出港查询卡片头,灰=时间线未达节点) - 复用 Pad 的矢量图:`img_search` `img_scan` `img_filter`(可 `app:tint` 染色) 设计稿里的 MDI 图标若缺失,直接写 24×24 的 vector(用 MDI 官方 path),比找位图靠谱且能染色。 diff --git a/.claude/skills/phone-adapt/references/proxyman.md b/.claude/skills/phone-adapt/references/proxyman.md new file mode 100644 index 0000000..185056b --- /dev/null +++ b/.claude/skills/phone-adapt/references/proxyman.md @@ -0,0 +1,76 @@ +# Proxyman MCP:抓包 / 直调 / Mock(阶段 2、5、6 的调试利器) + +Proxyman 桌面端 + `mcp__proxyman__*` 工具(会话内直接可用,缺 schema 时用 ToolSearch +`select:mcp__proxyman__get_flows,...` 加载)。**2026-07-31 已在出港查询页全链路实测**: +抓包核对请求体、Map Local mock 三种卡片形态(含真实数据不存在的「未入库」兜底态)一次跑通。 + +## 与 api-doc 的分工(先契约后事实) + +| | api-doc MCP | Proxyman MCP | +|---|---|---| +| 回答什么 | **契约**:接口该有什么入参/出参、参数名叫什么 | **事实**:App 实际发了什么、后端实际回了什么 | +| 用在何时 | 阶段 2 开工前逐接口核对 | 阶段 5/6 实机验证与 corner case 补测 | + +标准配合流程: +api-doc 拿权威参数名 → 前端实现 → Proxyman flow 核对请求体确实带上了 → +compose 改参 A/B 验证后端认不认 → 不认 → 记问题清单(附 `export_flow_curl` 证据)→ +map local 造 mock 补 UI corner case 验证。 + +## 接入(一次性,实测步骤) + +```bash +# 1) 确认 Proxyman 在跑(返回 Recording: Active + 端口,默认 9090) +# mcp__proxyman__get_proxy_status +# 2) 模拟器全局代理指向宿主机(模拟器视角宿主机 = 10.0.2.2) +adb -s shell settings put global http_proxy 10.0.2.2:9090 +# 3) 验证完【必须】清掉,否则 Proxyman 一关模拟器就断网,下次验证莫名全挂 +adb -s shell settings put global http_proxy :0 +``` + +本项目内网服务是**纯 HTTP**(192.168.1.250:8093)→ 不需要装证书,明文直接可见。 +(若未来切 HTTPS,才需要 `install_certificate` + `enable_ssl_proxying`。) + +## 场景 1:核对请求/响应(替代 `ui_probe req`) + +logcat 抓 OkHttp 多行 pretty JSON 脆弱且要人肉拼接;Proxyman 一步到位: + +- `filter_flows`(key=url, value="IntExpSearch")→ 拿 flow ID 列表 +- `get_flow_detail`(flow_id)→ 完整请求体 + 响应体 + headers(Authorization 自动脱敏) + +**出参无文档定义时(如 `IntExpSearch/detail` 返回裸 Map),用真实 flow 的 responseBody +直接盘点字段清单**——判定「锁定状态/计费重量是否存在」这类问题的最快路径。 + +## 场景 2:直调后端 A/B 验证(替代 run-as 提 token + 手写 curl) + +`create_compose_http_from_flow`(从真实 flow 复制请求,**token 自动带上,不用碰 +shared_prefs**)→ `update_compose_http` 改一个参数 → `send_compose_http` 看结果对比。 +isFclose 这类「参数是否生效」的 A/B 实验用这条链。给后端提缺口时用 +`export_flow_curl` 导出可复现的 curl 附进问题清单。 + +## 场景 3:Map Local 造 mock 验证 corner case(替代代码注入样例 Bean) + +老流程「Activity 临时注入 Bean → 截图 → 删码 → 重构建」彻底淘汰:**零代码改动、零重构建**。 + +- `create_map_local`:url 精确到接口路径,method=POST,response_body 直接写目标 JSON + (构造空字段/超长文本/罕见状态,比如出港查询的 fclose+opDate 双空「未入库」兜底态) +- 改真实响应个别字段更省事时用 `create_map_local_from_flow` +- 验证完 `delete_rule`(rule_type=maplocal)+ 清代理,**规则残留会污染后续真实数据验证** + +响应结构照抄真实 flow 的顶层结构(如 pageQuery 是裸 PageInfo:`{total, list, pages, ...}`, +不要包 `{status, data}`)。 + +⚠️ 实测坑:mock 响应到达后 UI 渲染可能滞后(冷启动首帧 Davey 卡顿 2s+), +**截图断言前先 `ui_probe texts` 确认数据已上屏**——这次就因截图太早误判过一轮「mock 没生效」, +其实 `get_flow_detail` 里 `matchedTools: ["Map Local"]` 早已证明规则命中,UI 只是还没画完。 + +## 场景 4:环境模拟(按需) + +- `create_network_condition`:弱网/高延迟,验证 loading 弹窗与超时提示 +- `create_breakpoint`:单次拦截改包(比 map local 更临时的一次性实验) +- `create_map_remote`:把请求转发到另一环境(如后端修复验证用的测试实例) + +## 验证收尾清单 + +- [ ] `list_rules` 确认无本次遗留规则(maplocal/breakpoint/network_condition) +- [ ] 模拟器代理已清(`settings get global http_proxy` 应为 `:0` 或空) +- [ ] 用真实数据再过一遍被 mock 过的页面,确认无假数据残影 diff --git a/CHANGELOG.md b/CHANGELOG.md index ae283ce..bb6c835 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,37 @@ ## [Unreleased] ### 新增 (Added) +- 「出港查询」5.5 寸手机端适配(设计稿 06_出港查询,含列表/详情/运单追踪三页): + 列表 `GjcQueryActivity` 手机布局 = PhoneSearchBar(运单号 + 扫码 + 筛选)+ 三格统计 + (总票数/已入库/已离港,彩色左边条卡片)+ 状态标签卡片(已离港绿/已入库橙/未入库灰, + 前端推断口径:fclose 非空=已离港,否则 opDate 非空=已入库);筛选弹层 9 项(平板搜索行的 + 日期起止/代理并入弹层,特码按设计稿改下拉,字典 `getSpecialCodeList(flag=1, ieFlag="")`, + 仅手机形态经 `initPhoneExtras()` 加载);详情 `GjcQueryDetailsActivity` 3 Tab 全部复用 + ViewPager2 + Fragment,手机变体以 PhoneKvItem 网格呈现「基本信息/件重信息/回执信息」, + 比平板多展示承运人/始发站/中转站/目的站/UN编号,入库件数/入库重量 = warehouseList 各批次求和; + 仓库/库位 Tab 改批次/库位卡片;「运单追踪」为公共页 `LogDetailActivity` 双变体首例—— + 手机竖排流转时间线(Activity `buildVerticalSteps` 动态构建,节点绿=已达/灰=未达 + 环节时间), + 平板横向步骤条零改动,手机标题按形态显示「运单追踪」 +- 手机首页「国际」Tab 增加「出港查询」入口(权限 AppIntExpSearch,图标复用 Pad 端 gjc_query_icon) +- `PhoneKvItem` 新增 `tagColor` 属性("green" 绿色高亮,海关放行正常态;默认 "orange"), + 且占位符 "-"/"--" 不再套高亮标签底 +- `GjcMaWb` 新增 `isQueryDeparted`/`isQueryStored`/`orDash` 手机版计算属性 +- 新增手机版资源:`ic_phone_package`(件数)、`ic_phone_tag`(特码)、`bg_phone_dot_blue/gray` +- 后端缺口 2 项登记问题清单 #21~#22(isFclose 入参实测被 pageQuery/pageQueryTotal 静默忽略且 + 无已入库/已离港分项统计出参;detail 出参无锁定状态/计费重量字段) + +### 修复 (Fixed) +- **`PhoneFilterPanel` 底部按钮被挤出屏幕**:面板高度 wrap_content 且内容插槽无滚动,筛选项多 + (出港查询 9 项)时「重置/确认」按钮直接超出屏幕外且无任何报错。修复:内容插槽外包 + ScrollView(weight=1),筛选项少时行为不变,超屏时内容区收缩滚动、按钮始终可见 + (已回归出港计重 4 项弹层,行为不变) + +### 验证 (Verified) +- 出港查询双端实机验证通过(2026-07-31,内网真实数据 2026-06-09 共 14 票): + 手机端登录→国际 Tab→出港查询菜单入口、列表加载/状态标签/三格统计(10+4=14 与卡片一致)、 + 筛选弹层(日期滚轮、特码/代理下拉真实取数、重置、确认后重新查询)、运单号搜索、扫码拉起、 + 详情 3 Tab(含仓库批次卡与库位空态)、运单追踪时间线、冷启动方向恒竖屏(mRotation=0×8 采样)、 + 全程 FATAL 0;平板端回归:列表 5 搜索条 + 底部统计 + 侧滑筛选面板 + 详情表格样式均与改造前一致 - 「出港运抵」5.5 寸手机端适配(主列表 + 3 个手机专属新页,设计稿 04_出港运抵): 主列表 `IntExpArriveActivity` 新增「待运抵/已运抵」Tab(客户端按 declareStatus 是否为空拆分数据集, 接口无此查询参数)+ 卡片长按浮层(待运抵→补充、已运抵→重置+回执,纯 UI 长按)+ 底部全选/已选/申报 diff --git a/CLAUDE.md b/CLAUDE.md index d8503b5..e7ae668 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1053,7 +1053,7 @@ DataBinding 适配器统一放在 `PhoneWidgetKtx.kt`(同名属性按控件类 | `PhoneFilterPanel` | 底部筛选弹层(遮罩 + 面板 + 重置/确认) | `title`、`panelVisible`、`setOnResetClick`、`setOnConfirmClick`、`setOnDismissClick` | | `PhoneBottomBar` | 底部操作条:全选 + 已选统计 + 主按钮 | `allChecked`、`countText`、`actionText`、`setOnAllCheckClick`、`setOnActionClick` | | `PhoneStatBox` | 卡片内 2~4 列统计框(未传 label 的列自动隐藏) | `label1..4`、`value1..4` | -| `PhoneKvItem` | 详情页字段项(灰标签 + 数值),`tag=true` 转橙色高亮 | `title`、`value`、`tag` | +| `PhoneKvItem` | 详情页字段项(灰标签 + 数值),`tag=true` 转高亮标签(占位符 "-"/"--" 不套底) | `title`、`value`、`tag`、`tagColor`("orange" 默认/"green") | | `PhoneFormRow` | 行式表单项(左标签+右值+分隔线),`PhoneFormRowType` = `INPUT`/`SELECT`(内置底部选择面板)/`DATE`/`TEXT`(只读右对齐,空值 "--") | `title`、`hint`、`type`、`value`(双向)、`list`、`required`、`enable`、`numeric`、`setRefreshCallBack` | `PhoneBottomBar` 追加 `actionDanger` 属性:true 时主按钮转浅红底红字 + 垃圾桶图标(ULD 管理批量删除)。 @@ -1061,6 +1061,9 @@ DataBinding 适配器统一放在 `PhoneWidgetKtx.kt`(同名属性按控件类 `ic_phone_trash`、`ic_phone_edit`、色值 `phone_danger_bg/text`。 出港计重追加:`bg_phone_btn_weak`(浅蓝弱按钮,卡片内提前运抵)、`bg_phone_card_top_accent` (卡片顶部主色描边条)、`ic_phone_clipboard`(FAB 剪贴板)、`ic_phone_weight`(砝码图标,可 tint)。 +出港查询追加:`ic_phone_package`(件数)、`ic_phone_tag`(特码)、`bg_phone_dot_blue/gray`(状态圆点); +`PhoneFilterPanel` 内容插槽已内置 ScrollView(筛选项超屏时收缩滚动,底部按钮始终可见—— +9 个筛选项曾把「重置/确认」挤出屏幕)。 ⚠️ **弹层与浮动按钮的层级**:`PhoneFilterPanel` 默认无 elevation,页面里有带 elevation 的浮动按钮(FAB)时 会穿透到弹层之上——给弹层实例加 `android:elevation="8dp"`(大于 FAB 的 6dp)。 @@ -1129,6 +1132,15 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = `.checked.set(...)` 会崩溃——接收方 `initOnCreated` 必须对列表 `.map { it.copy() }` 补上。 2026-07-30 review 修正:状态重置弹框改手机底部弹层(弹框双变体首例,见改造步骤第 6 条)、 主列表/回执页补空态、分单浮层补「回执」、分单统计加分母、Tab 角标初始 0 + - 「出港查询」`GjcQueryActivity`(列表:三格统计 总票数/已入库/已离港 + 卡片状态标签, + 状态为前端推断:`fclose` 非空=已离港/`opDate` 非空=已入库;筛选弹层 9 项,日期起止与代理 + 从平板搜索行并入,特码改下拉 `getSpecialCodeList(flag=1, ieFlag="")`;分项统计为已加载 + 数据客户端计数,`isFclose` 实测被后端忽略,缺口 #21)+ `GjcQueryDetailsActivity`(3 Tab + 复用 ViewPager2+Fragment,手机变体 PhoneKvItem 网格;入库件数/重量= warehouseList 求和; + 锁定状态/计费重量后端无字段,缺口 #22)+ 「运单追踪」`LogDetailActivity`(app 模块公共页 + 双变体首例:手机竖排时间线由 Activity `buildVerticalSteps` 动态构建,平板横向步骤条不动; + 手机标题按形态切「运单追踪」)。平板侧滑筛选面板代码已判空守卫(手机变体无 filter_panel + include,Binding 字段为 @Nullable) - ⏳ **待办**: - `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 a169c60..a344348 100644 --- a/app/src/debug/AndroidManifest.xml +++ b/app/src/debug/AndroidManifest.xml @@ -104,5 +104,23 @@ android:exported="true" tools:replace="android:exported" /> + + + + + + + + + diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/log/detail/LogDetailActivity.kt b/app/src/main/java/com/lukouguoji/aerologic/page/log/detail/LogDetailActivity.kt index 5c254a0..9214019 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/log/detail/LogDetailActivity.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/log/detail/LogDetailActivity.kt @@ -19,6 +19,7 @@ import com.lukouguoji.module_base.base.BaseBindingActivity import com.lukouguoji.module_base.bean.LogBean import com.lukouguoji.module_base.common.Constant import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil @Route(path = ARouterConstants.ACTIVITY_URL_LOG_DETAIL) class LogDetailActivity : BaseBindingActivity() { @@ -34,7 +35,8 @@ class LogDetailActivity : BaseBindingActivity, + activeCodes: Set, + latestCode: String + ) { + val container = binding.llSteps + container.removeAllViews() + container.orientation = LinearLayout.VERTICAL + + val logs = viewModel.statusLogList.value ?: emptyList() + val colorGreen = 0xFF16A34A.toInt() + val colorGray = 0xFF9CA3AF.toInt() + val colorLine = 0xFFE5E7EB.toInt() + + for (i in steps.indices) { + val step = steps[i] + val isActive = step.code in activeCodes + val isLast = i == steps.size - 1 + val time = logs.lastOrNull { it.status == step.code }?.opDate ?: "" + + val row = LinearLayout(this).apply { + orientation = LinearLayout.HORIZONTAL + layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + } + + // 左列:圆点 + 连接竖线 + val dotColumn = LinearLayout(this).apply { + orientation = LinearLayout.VERTICAL + gravity = Gravity.CENTER_HORIZONTAL + layoutParams = LinearLayout.LayoutParams(dp(20), LinearLayout.LayoutParams.MATCH_PARENT) + } + val dot = View(this).apply { + setBackgroundResource( + if (isActive) com.lukouguoji.module_base.R.drawable.bg_phone_dot_green + else com.lukouguoji.module_base.R.drawable.bg_phone_dot_gray + ) + layoutParams = LinearLayout.LayoutParams( + dp(if (isActive) 12 else 8), dp(if (isActive) 12 else 8) + ).apply { topMargin = dp(if (isActive) 2 else 4) } + } + dotColumn.addView(dot) + if (!isLast) { + val line = View(this).apply { + setBackgroundColor(colorLine) + layoutParams = LinearLayout.LayoutParams(dp(2), 0).apply { + weight = 1f + topMargin = dp(2) + bottomMargin = dp(2) + } + } + dotColumn.addView(line) + } + row.addView(dotColumn) + + // 右列:步骤名 + 时间 + val content = LinearLayout(this).apply { + orientation = LinearLayout.VERTICAL + layoutParams = LinearLayout.LayoutParams( + 0, LinearLayout.LayoutParams.WRAP_CONTENT + ).apply { + weight = 1f + leftMargin = dp(10) + } + setPadding(0, 0, 0, if (isLast) 0 else dp(24)) + } + content.addView(TextView(this).apply { + text = step.name + setTextSize(TypedValue.COMPLEX_UNIT_SP, 15f) + setTextColor(if (isActive) colorGreen else colorGray) + if (isActive) setTypeface(typeface, android.graphics.Typeface.BOLD) + }) + if (time.isNotEmpty()) { + content.addView(TextView(this).apply { + text = time + setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f) + setTextColor(colorGray) + layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ).apply { topMargin = dp(4) } + }) + } + row.addView(content) + + container.addView(row) + } } private fun buildStepProgressBar( diff --git a/app/src/main/res/layout-sw600dp/activity_log_detail.xml b/app/src/main/res/layout-sw600dp/activity_log_detail.xml new file mode 100644 index 0000000..2f55b92 --- /dev/null +++ b/app/src/main/res/layout-sw600dp/activity_log_detail.xml @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_log_detail.xml b/app/src/main/res/layout/activity_log_detail.xml index 2f55b92..577c215 100644 --- a/app/src/main/res/layout/activity_log_detail.xml +++ b/app/src/main/res/layout/activity_log_detail.xml @@ -1,6 +1,22 @@ + + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> @@ -12,7 +28,7 @@ @@ -20,208 +36,99 @@ + android:fillViewport="true" + android:overScrollMode="never"> + android:padding="12dp"> - + + android:background="@drawable/bg_phone_card" + android:orientation="vertical" + android:padding="16dp"> - - - - - - - - - - + + android:gravity="center_vertical" + android:orientation="horizontal"> - + android:layout_weight="1" + android:text="@{viewModel.waybillNo}" + android:textColor="@color/phone_text_title" + android:textSize="20sp" + android:textStyle="bold" + tools:text="78133358743" /> - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_gravity="center_horizontal" + android:layout_marginTop="24dp" + android:layout_marginBottom="16dp" + android:letterSpacing="0.3" + android:text="查询信息已触底" + android:textColor="@color/phone_text_hint" + android:textSize="12sp" /> diff --git a/documents/后端接口对接问题清单.xlsx b/documents/后端接口对接问题清单.xlsx index 4f3435e7a82d1799b566aae0660d3ce7e0b19ff8..59eab0a388cca601ea761164e2e749f40b5fc4e5 100644 GIT binary patch delta 10109 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 T_1~=>{0fWw2!=foE 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 e0^MJXIUE4+mzn if (declareStatus.isNullOrEmpty()) "" else "amber" } + /** + * 5.5寸手机版-出港查询:卡片状态标签。 + * 已离港 = 航班关闭时间(fclose)非空;已入库 = 入库时间(opDate)非空;都为空 = 未入库(灰)。 + * 接口无独立状态出参,此判定为前端推断(与卡片「入库时间/离港时间」两列同源)。 + */ + val isQueryDeparted: Boolean + get() = !fclose.isNullOrEmpty() + + val isQueryStored: Boolean + get() = !opDate.isNullOrEmpty() + + /** 5.5寸手机版:空值统一占位 "--"(空串与 null 都兜底,布局绑定用) */ + fun orDash(value: String?): String = if (value.isNullOrEmpty()) "--" else value + // ==================== 状态转换扩展属性 ==================== /** * 计重状态中文 diff --git a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneKvItem.kt b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneKvItem.kt index aaa1ac0..bb78c80 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneKvItem.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneKvItem.kt @@ -56,13 +56,25 @@ class PhoneKvItem @JvmOverloads constructor( applyStyle() } + /** 高亮标签配色:"orange"(默认,如库位)/ "green"(如海关放行正常态) */ + var tagColor: String = "orange" + set(v) { + field = v + applyStyle() + } + /** - * 空值不套高亮标签底 —— 否则占位符 "-" 会显示成一个孤零零的橙色小方块。 + * 空值不套高亮标签底 —— 否则占位符 "-"/"--" 会显示成一个孤零零的色块。 */ private fun applyStyle() { - if (tag && value.isNotEmpty()) { - tvValue.setBackgroundResource(R.drawable.bg_phone_value_orange) - tvValue.setTextColor(ContextCompat.getColor(context, R.color.phone_orange_text)) + if (tag && value.isNotEmpty() && value != "-" && value != "--") { + if (tagColor == "green") { + tvValue.setBackgroundResource(R.drawable.bg_phone_tag_green) + tvValue.setTextColor(ContextCompat.getColor(context, R.color.phone_tag_green_text)) + } else { + tvValue.setBackgroundResource(R.drawable.bg_phone_value_orange) + tvValue.setTextColor(ContextCompat.getColor(context, R.color.phone_orange_text)) + } tvValue.setTypeface(tvValue.typeface, android.graphics.Typeface.BOLD) val padH = (4 * resources.displayMetrics.density).toInt() tvValue.setPadding(padH, 0, padH, 0) 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 0134839..a5438c3 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 @@ -219,10 +219,17 @@ fun setPhoneStatBoxAttrs( // PhoneKvItem /////////////////////////////////////////////////////////////////////////// -@BindingAdapter("title", "value", "tag", requireAll = false) -fun setPhoneKvItemAttrs(item: PhoneKvItem, title: String?, value: String?, tag: Boolean?) { +@BindingAdapter("title", "value", "tag", "tagColor", requireAll = false) +fun setPhoneKvItemAttrs( + item: PhoneKvItem, + title: String?, + value: String?, + tag: Boolean?, + tagColor: String? +) { title?.let { item.title = it } - // tag 需先于 value 生效,确保样式切换后再填内容 + // tag/tagColor 需先于 value 生效,确保样式切换后再填内容 + tagColor?.let { item.tagColor = it } tag?.let { item.tag = it } item.value = value.orEmpty() } diff --git a/module_base/src/main/res/drawable/bg_phone_dot_blue.xml b/module_base/src/main/res/drawable/bg_phone_dot_blue.xml new file mode 100644 index 0000000..f076187 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_dot_blue.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_dot_gray.xml b/module_base/src/main/res/drawable/bg_phone_dot_gray.xml new file mode 100644 index 0000000..204e516 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_dot_gray.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_package.xml b/module_base/src/main/res/drawable/ic_phone_package.xml new file mode 100644 index 0000000..45bfe57 --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_package.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_tag.xml b/module_base/src/main/res/drawable/ic_phone_tag.xml new file mode 100644 index 0000000..8db7a99 --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_tag.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/module_base/src/main/res/layout/layout_phone_filter_panel.xml b/module_base/src/main/res/layout/layout_phone_filter_panel.xml index 1499ea2..f4e714a 100644 --- a/module_base/src/main/res/layout/layout_phone_filter_panel.xml +++ b/module_base/src/main/res/layout/layout_phone_filter_panel.xml @@ -44,12 +44,24 @@ - - + + android:layout_weight="1" + android:overScrollMode="never" + android:scrollbars="none"> + + + + - if (visible) showFilterPanel() else hideFilterPanel() + // 平板变体才有侧滑筛选面板(filter_panel/filter_overlay 手机变体不存在,Binding 字段为 null) + val padFilterPanel = binding.filterPanel + if (padFilterPanel != null) { + // 观察筛选面板显示状态(滑入/滑出动画) + viewModel.filterVisible.observe(this) { visible -> + if (visible) showFilterPanel() else hideFilterPanel() + } + + // 航班号:大写字母+数字 + padFilterPanel.filterFlightNo.et.setUpperCaseAlphanumericFilter() + // 目的港:仅大写字母 + padFilterPanel.filterDest.et.setUpperCaseLetterFilter() + } else { + // 手机变体:PhoneFilterPanel 的显隐由 XML 直接绑定 viewModel.filterVisible,无需动画代码 + binding.phoneFilterFlightNo?.et?.setUpperCaseAlphanumericFilter() + binding.phoneFilterDest?.et?.setUpperCaseLetterFilter() } - // 航班号:大写字母+数字 - binding.filterPanel.filterFlightNo.et.setUpperCaseAlphanumericFilter() - // 目的港:仅大写字母 - binding.filterPanel.filterDest.et.setUpperCaseLetterFilter() + // 手机形态专属:特码下拉字典 + 已入库/已离港统计 + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } // 初始加载 viewModel.refresh() } private fun showFilterPanel() { - val panel = binding.filterPanel.root - val overlay = binding.filterOverlay + val panel = binding.filterPanel?.root ?: return + val overlay = binding.filterOverlay ?: return val panelWidth = window.decorView.width / 3 panel.layoutParams = (panel.layoutParams as FrameLayout.LayoutParams).apply { @@ -86,8 +100,8 @@ class GjcQueryActivity : } private fun hideFilterPanel() { - val panel = binding.filterPanel.root - val overlay = binding.filterOverlay + val panel = binding.filterPanel?.root ?: return + val overlay = binding.filterOverlay ?: return if (panel.visibility != View.VISIBLE) return diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryDetailsViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryDetailsViewModel.kt index c9bec27..e77286e 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryDetailsViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryDetailsViewModel.kt @@ -34,6 +34,11 @@ class GjcQueryDetailsViewModel : BaseViewModel() { // 库位列表 (storageUseList) val storageUseList = MutableLiveData>>(emptyList()) + // ==================== 5.5寸手机版专属(展示用,平板布局不绑定) ==================== + // 入库件数/入库重量 = warehouseList 各批次求和(设计稿「件重信息」区块) + val inPcTotal = MutableLiveData("--") + val inWeightTotal = MutableLiveData("--") + // ==================== Fragment列表 ==================== val fragmentList by lazy { listOf( @@ -59,6 +64,40 @@ class GjcQueryDetailsViewModel : BaseViewModel() { currentTab.value = index } + // ==================== 5.5寸手机版取值帮助方法(布局绑定用) ==================== + // 表达式里必须把 map(maWbData)作为参数传入,DataBinding 才能追踪依赖并在数据到达后刷新 + + /** + * 从详情 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 的展示值(如 agentName 优先于 agentCode) + */ + 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 { "--" } + } + } + /** * 加载详情数据 */ @@ -111,6 +150,17 @@ class GjcQueryDetailsViewModel : BaseViewModel() { val whList = data["warehouseList"] as? List> ?: emptyList() warehouseList.value = whList + // 手机版「入库件数/入库重量」= 各批次求和(Gson 反序列化数字均为 Double) + if (whList.isNotEmpty()) { + val pcSum = whList.sumOf { (it["pc"] as? Double) ?: 0.0 } + val weightSum = whList.sumOf { (it["weight"] as? Double) ?: 0.0 } + inPcTotal.value = pcSum.toLong().toString() + inWeightTotal.value = weightSum.toString() + } else { + inPcTotal.value = "--" + inWeightTotal.value = "--" + } + // 解析 storageUseList 列表 @Suppress("UNCHECKED_CAST") val suList = data["storageUseList"] as? List> ?: emptyList() diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryViewModel.kt index 69034e8..d5c112b 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.MutableLiveData import com.lukouguoji.gjc.R import com.lukouguoji.gjc.holder.GjcQueryViewHolder import com.lukouguoji.module_base.base.BasePageViewModel +import com.lukouguoji.module_base.bean.GjcMaWb import com.lukouguoji.module_base.common.Constant import com.lukouguoji.module_base.http.net.NetApply import com.lukouguoji.module_base.ktx.launchCollect @@ -76,6 +77,31 @@ class GjcQueryViewModel : BasePageViewModel() { val businessType = MutableLiveData("") // 业务类型 val goodsCn = MutableLiveData("") // 品名(中) + // ==================== 5.5寸手机版专属 ==================== + // 特码下拉列表(设计稿筛选弹层为下拉;平板筛选为文本输入,不加载) + val specialCodeList = MutableLiveData>(emptyList()) + + // 三格统计:已入库 / 已离港(总票数复用 totalCount,为服务端全量口径) + // 后端无分项统计出参,且文档定义的 isFclose 入参实测被 pageQuery/pageQueryTotal 静默忽略 + // (2026-07-31 内网 A/B 验证,见接口问题清单)——已入库/已离港暂为「已加载数据」客户端计数口径 + val storedCount = MutableLiveData("0") + val departedCount = MutableLiveData("0") + + private var phoneExtrasEnabled = false + private var phoneLoadedList: List = emptyList() + + /** + * 手机形态专属初始化(Activity 在 DeviceUtil.isPhone() 时调用)。 + * 平板端不调用,请求次数与行为零变化。 + */ + fun initPhoneExtras() { + phoneExtrasEnabled = true + // flag=1 国际;ieFlag 必须留空——传 "E" 后端返回空数组(与既有国际出港页面口径一致) + DictUtils.getSpecialCodeList(addAll = false, flag = 1, ieFlag = "") { list -> + specialCodeList.postValue(listOf(KeyValue("全部", "")) + list) + } + } + // 是否有筛选条件(任意一个非空则为 true,用于筛选按钮红点) val hasFilter: MediatorLiveData = MediatorLiveData().apply { val update = { _: Any? -> @@ -201,6 +227,14 @@ class GjcQueryViewModel : BasePageViewModel() { onSuccess = { pageInfo -> // ⚠️ 核心:使用toBaseListBean()转换PageInfo为BaseListBean pageModel.handleListBean(pageInfo.toBaseListBean()) + + // 手机三格统计:对已加载数据做客户端计数(平板不触发) + if (phoneExtrasEnabled) { + val pageItems = pageInfo.list ?: emptyList() + phoneLoadedList = + if (pageModel.page <= 1) pageItems else phoneLoadedList + pageItems + updatePhoneCounts() + } } } @@ -217,6 +251,16 @@ class GjcQueryViewModel : BasePageViewModel() { } } + /** + * 手机三格统计(已入库/已离港):与卡片状态标签同一判定口径(fclose / opDate), + * 统计范围为已加载的列表数据。 + */ + private fun updatePhoneCounts() { + departedCount.value = phoneLoadedList.count { it.isQueryDeparted }.toString() + storedCount.value = + phoneLoadedList.count { !it.isQueryDeparted && it.isQueryStored }.toString() + } + /** * 处理扫码结果 */ diff --git a/module_gjc/src/main/res/layout-sw600dp/activity_gjc_query.xml b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_query.xml new file mode 100644 index 0000000..1b60f63 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_query.xml @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/activity_gjc_query_details.xml b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_query_details.xml new file mode 100644 index 0000000..34b34b7 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_query_details.xml @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/fragment_gjc_query_storage.xml b/module_gjc/src/main/res/layout-sw600dp/fragment_gjc_query_storage.xml new file mode 100644 index 0000000..43d5ba2 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/fragment_gjc_query_storage.xml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/fragment_gjc_query_warehouse.xml b/module_gjc/src/main/res/layout-sw600dp/fragment_gjc_query_warehouse.xml new file mode 100644 index 0000000..c9f7f93 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/fragment_gjc_query_warehouse.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/fragment_gjc_query_waybill.xml b/module_gjc/src/main/res/layout-sw600dp/fragment_gjc_query_waybill.xml new file mode 100644 index 0000000..0917122 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/fragment_gjc_query_waybill.xml @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/item_gjc_query.xml b/module_gjc/src/main/res/layout-sw600dp/item_gjc_query.xml new file mode 100644 index 0000000..3f4902f --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/item_gjc_query.xml @@ -0,0 +1,318 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/item_gjc_query_storage.xml b/module_gjc/src/main/res/layout-sw600dp/item_gjc_query_storage.xml new file mode 100644 index 0000000..7eec041 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/item_gjc_query_storage.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/item_gjc_query_warehouse.xml b/module_gjc/src/main/res/layout-sw600dp/item_gjc_query_warehouse.xml new file mode 100644 index 0000000..09418f9 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/item_gjc_query_warehouse.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/layout_gjc_query_filter.xml b/module_gjc/src/main/res/layout-sw600dp/layout_gjc_query_filter.xml similarity index 100% rename from module_gjc/src/main/res/layout/layout_gjc_query_filter.xml rename to module_gjc/src/main/res/layout-sw600dp/layout_gjc_query_filter.xml diff --git a/module_gjc/src/main/res/layout/activity_gjc_query.xml b/module_gjc/src/main/res/layout/activity_gjc_query.xml index 1b60f63..e1aefee 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_query.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_query.xml @@ -1,208 +1,201 @@ + + - + + - + android:background="@color/phone_page_bg"> - - - - - + android:layout_height="match_parent" + android:orientation="vertical"> - + + + + android:layout_height="wrap_content" + android:background="@color/white" + android:orientation="vertical" + android:paddingHorizontal="16dp" + android:paddingTop="16dp" + android:paddingBottom="12dp"> - - + + + + + + + + - - + - - - - - - - - - - - - - + android:orientation="vertical" + android:paddingHorizontal="12dp" + android:paddingVertical="10dp"> - - + - - - - - - - - + - - - - - - - - + + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="10dp" + android:layout_weight="1" + android:background="@drawable/bg_phone_card" + android:orientation="horizontal"> + + - + android:orientation="vertical" + android:paddingHorizontal="12dp" + android:paddingVertical="10dp"> + android:text="已入库" + android:textColor="@color/phone_text_body" + android:textSize="12sp" /> + tools:text="2" /> + + + + + + + + + + + + + + tools:text="2" /> @@ -210,28 +203,131 @@ - - + + android:layout_height="0dp" + android:layout_weight="1"> - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - diff --git a/module_gjc/src/main/res/layout/activity_gjc_query_details.xml b/module_gjc/src/main/res/layout/activity_gjc_query_details.xml index 34b34b7..99ccbf2 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_query_details.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_query_details.xml @@ -1,125 +1,137 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/fragment_gjc_query_storage.xml b/module_gjc/src/main/res/layout/fragment_gjc_query_storage.xml index 43d5ba2..4211277 100644 --- a/module_gjc/src/main/res/layout/fragment_gjc_query_storage.xml +++ b/module_gjc/src/main/res/layout/fragment_gjc_query_storage.xml @@ -1,137 +1,53 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/fragment_gjc_query_warehouse.xml b/module_gjc/src/main/res/layout/fragment_gjc_query_warehouse.xml index c9f7f93..4a16117 100644 --- a/module_gjc/src/main/res/layout/fragment_gjc_query_warehouse.xml +++ b/module_gjc/src/main/res/layout/fragment_gjc_query_warehouse.xml @@ -1,157 +1,53 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/fragment_gjc_query_waybill.xml b/module_gjc/src/main/res/layout/fragment_gjc_query_waybill.xml index 0917122..1c106f1 100644 --- a/module_gjc/src/main/res/layout/fragment_gjc_query_waybill.xml +++ b/module_gjc/src/main/res/layout/fragment_gjc_query_waybill.xml @@ -1,319 +1,452 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_gjc_query.xml b/module_gjc/src/main/res/layout/item_gjc_query.xml index 3f4902f..def293b 100644 --- a/module_gjc/src/main/res/layout/item_gjc_query.xml +++ b/module_gjc/src/main/res/layout/item_gjc_query.xml @@ -1,318 +1,226 @@ + + xmlns:tools="http://schemas.android.com/tools"> + + + - - - - - - - - + android:layout_height="wrap_content" + 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" /> - - + + - + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - diff --git a/module_gjc/src/main/res/layout/item_gjc_query_storage.xml b/module_gjc/src/main/res/layout/item_gjc_query_storage.xml index 7eec041..dcf07d5 100644 --- a/module_gjc/src/main/res/layout/item_gjc_query_storage.xml +++ b/module_gjc/src/main/res/layout/item_gjc_query_storage.xml @@ -1,99 +1,113 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_gjc_query_warehouse.xml b/module_gjc/src/main/res/layout/item_gjc_query_warehouse.xml index 09418f9..acac4de 100644 --- a/module_gjc/src/main/res/layout/item_gjc_query_warehouse.xml +++ b/module_gjc/src/main/res/layout/item_gjc_query_warehouse.xml @@ -1,119 +1,136 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 77a6405..dfbba7b 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 @@ -60,6 +60,12 @@ class GjViewModel : BaseViewModel() { Constant.AuthName.GjcIntExpArrive, ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE ), + ActionBean( + "出港查询", + R.drawable.gjc_query_icon, + Constant.AuthName.GjcQueryListActivity, + ARouterConstants.ACTIVITY_URL_GJC_QUERY_LIST + ), // ULD管理属综合管理业务(Pad 端在「综合管理」菜单组),手机端首页暂无综合 Tab,挂在国际 Tab 下 ActionBean( "ULD管理", diff --git a/module_p/src/main/res/drawable-xxhdpi/gjc_query_icon.png b/module_p/src/main/res/drawable-xxhdpi/gjc_query_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..76433e263a328f5efa873e2227c5ef34c3896d06 GIT binary patch literal 32301 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 Date: Fri, 31 Jul 2026 20:49:59 +0800 Subject: [PATCH 08/29] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=87=BA?= =?UTF-8?q?=E6=B8=AF=E4=BB=93=E5=BA=93=E4=B8=8E=E8=BF=9B=E6=B8=AF=E4=BB=93?= =?UTF-8?q?=E5=BA=93=E9=A1=B5=E9=9D=A25.5=E5=AF=B8=E6=89=8B=E6=9C=BA?= =?UTF-8?q?=E7=AB=AF=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 From b2a2cce58565b27d5d6ff6bfe5dd3889dbde401c Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 31 Jul 2026 21:31:58 +0800 Subject: [PATCH 09/29] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E6=8F=90?= =?UTF-8?q?=E5=8F=96=E5=87=BA=E5=BA=93=E9=A1=B5=E9=9D=A25.5=E5=AF=B8?= =?UTF-8?q?=E6=89=8B=E6=9C=BA=E7=AB=AF=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 提取出库(09,module_gjj): - IntImpPickUpDLVActivity 手机布局:搜索行+待出库/已出库状态Tab(outState 为 pageQuery 文档定义入参 0/1,Tab 真实过滤+角标双 pageQueryTotal,抓包证实携带) +双形态卡片(isPickedUp=dlvTime非空:待出库勾选框+橙标签+库位行/已出库绿√+ 出库人·出库时间行)+卡片内 PhoneStatBox 三列+PhoneBottomBar(仅待出库Tab显示, 复用既有 confirmOutbound) - 手机专属新页 IntImpPickUpDetailActivity 运单详情:蓝头运单卡+绿头提货信息卡, Intent 传 Serializable bean 零新增请求 - 筛选弹层 4 项(航班日期为未定义入参预留传参);手机进入时清空平板默认 「当天缴费日期」查全量,平板默认值不变 - IntImpPickUpDLVBean 增加 isPickedUp 计算属性;手机首页「国际」Tab 加入口 修复:checkAllClick 全选后底部「已选 N 项」不更新(批量勾选不走单卡 FlowBus 事件,需自行同步 selectedCountText),实测修复生效 验证:双端 Proxyman Map Local mock 口径验证通过,平板回归一致(含缴费日期默认值), 崩溃 0;后端缺口 2 项登记问题清单 #28~#29(无 fdate 入参、出参无车牌/目的港/ 业务类型;outState 过滤与 dlvName=出库人语义待内网实测) Co-Authored-By: Claude Fable 5 --- .../skills/phone-adapt/references/api-doc.md | 8 + CHANGELOG.md | 24 + CLAUDE.md | 9 + app/src/debug/AndroidManifest.xml | 12 + app/src/main/AndroidManifest.xml | 7 + documents/后端接口对接问题清单.xlsx | Bin 21738 -> 22454 bytes .../module_base/bean/IntImpPickUpDLVBean.kt | 7 + .../gjj/activity/IntImpPickUpDLVActivity.kt | 6 +- .../activity/IntImpPickUpDetailActivity.kt | 45 ++ .../gjj/holder/IntImpPickUpDLVViewHolder.kt | 22 +- .../gjj/viewModel/IntImpPickUpDLVViewModel.kt | 94 +++- .../activity_int_imp_pick_up_dlv.xml | 204 +++++++++ .../item_int_imp_pick_up_dlv.xml | 266 +++++++++++ .../activity_int_imp_pick_up_detail.xml | 340 ++++++++++++++ .../layout/activity_int_imp_pick_up_dlv.xml | 306 ++++++------- .../res/layout/item_int_imp_pick_up_dlv.xml | 422 ++++++++---------- .../sixin/module_p/ui/enter/gj/GjViewModel.kt | 6 + .../res/drawable-xxhdpi/gjj_chu_ku_icon.png | Bin 0 -> 31774 bytes 18 files changed, 1369 insertions(+), 409 deletions(-) create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpPickUpDetailActivity.kt create mode 100644 module_gjj/src/main/res/layout-sw600dp/activity_int_imp_pick_up_dlv.xml create mode 100644 module_gjj/src/main/res/layout-sw600dp/item_int_imp_pick_up_dlv.xml create mode 100644 module_gjj/src/main/res/layout/activity_int_imp_pick_up_detail.xml create mode 100644 module_p/src/main/res/drawable-xxhdpi/gjj_chu_ku_icon.png diff --git a/.claude/skills/phone-adapt/references/api-doc.md b/.claude/skills/phone-adapt/references/api-doc.md index 62c4e22..93a3cb5 100644 --- a/.claude/skills/phone-adapt/references/api-doc.md +++ b/.claude/skills/phone-adapt/references/api-doc.md @@ -101,6 +101,14 @@ curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \ `awbPc`/`awbWeight`/`cashWeight`/`inPc`/`inWeight`/`lockState`(0/1 需转中文)/`mftStatus` 原始舱单/ `tallyStatus` 理货报告/`command` 海关放行/`by1` 承运人/`dlvTime` 出库时间;`dep`/`dest1`/`dest`/ `unNumber`/`opDate` 为按出港推断,待实测 #27) +- `IntImpPickUpDlv`(提取出库,2026-07-31 文档核对):`pageQuery` 入参含 **`outState` + (0 未出库/1 已出库)**——待出库/已出库 Tab 直接真实过滤(抓包证实携带,效果待内网 A/B #29); + 另有 `fno`/`dest`/`origin`/`carrier`/`awbType`/`businessType`/`goods`/`likeNo`/`pkId`/ + `beginDate`/`endDate`+`dateType`(0 入库/1 离港)/`chargeFlag`(0 未提取/1 已提取); + **无 `fdate`(航班日期)入参**(缺口 #28);出参无车牌/目的港/业务类型名称(#28); + 运单号筛选参数名是 **`no`**(平板既有口径);`chargeName`/`chargeTime` = 柜台办理人/缴费(提取)时间, + `dlvTime` = 出库时间,`dlvName` 按提货人语义推断作「出库人」展示(待确认 #29); + 确认出库接口 `pickUpOut` 文档注明**需将全字段传至后端**(平板 `selectedItems.toRequestBody()` 已满足) - `IntExpCheckIn`(出港计重,2026-07-29 内网实测):`likeNo` **并非任意模糊**——按 8 位 `no` 匹配(11 位 wbNo 或部分号均 0 条),11 位全号必须走 `wbNo`;`checkIn`/`checkInList` 文档有定义但 `pageQuery`/`pageQueryTotal` **均静默忽略**(缺口 #12,待计重/计重中计数依赖); diff --git a/CHANGELOG.md b/CHANGELOG.md index a753159..94db5db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,22 @@ ## [Unreleased] ### 新增 (Added) +- 「提取出库」5.5 寸手机端适配(设计稿 09_提取出库):列表 `IntImpPickUpDLVActivity`(module_gjj) + 手机布局 = PhoneSearchBar(运单号+扫码+筛选)+ **PhoneStatusTab 待出库/已出库**(`outState` + 为 pageQuery 文档定义入参 0/1,Tab 真实过滤 + 角标双 pageQueryTotal,抓包证实携带)+ + 双形态卡片(待出库:圆形勾选框+橙标签+库位行;已出库:绿 √ 标签+出库人·出库时间行, + `isPickedUp` = dlvTime 非空)+ 卡片内 PhoneStatBox 三列(代理人/件数/重量)+「查看详情」链接 + + PhoneBottomBar(全选+已选 N 项+出库,仅待出库 Tab 显示,复用既有 confirmOutbound); + 筛选弹层 4 项(航班日期为 pageQuery 未定义入参预留;航班号 fno;代理人/特码下拉); + 手机端进入时清空平板默认「当天缴费日期」查全量(initPhoneExtras,平板默认值不变) +- 手机专属新页「运单详情」`IntImpPickUpDetailActivity`:蓝头运单卡(红标签国际进港+品名大标题+ + 两列 KV+库位橙标签)+ 绿头提货信息卡(柜台办理人/时间,已出库追加出库人/出库时间行), + 数据直接 Intent 传列表 bean(Serializable),零新增请求 +- `IntImpPickUpDLVBean` 新增 `isPickedUp` 计算属性;手机首页「国际」Tab 增加「提取出库」入口 + (权限 AppIntImpPickUpDLV 对应权限串,图标复用 Pad 端 gjj_chu_ku_icon) +- 后端缺口 2 项登记问题清单 #28~#29(pageQuery 无 fdate 入参、出参无车牌/目的港/业务类型; + outState 过滤与 dlvName=出库人语义待内网实测) + - 「进港仓库」5.5 寸手机端适配(设计稿 08_进港仓库,07 出港仓库的进港镜像 + 进港详情页首次适配): 列表 `IntImpStorageUseActivity`(module_gjj,首页菜单实际跳转页;旧版 `GjjWareHouseActivity` 路由已注释弃用)手机布局 = PhoneSearchBar(placeholder「搜索运单号/航班号」,`phoneSearchClick` @@ -64,12 +80,20 @@ 无已入库/已离港分项统计出参;detail 出参无锁定状态/计费重量字段) ### 修复 (Fixed) +- 提取出库手机版底部条「已选 N 项」在点全选后不更新:`checkAllClick` 只改勾选状态未同步 + `selectedCountText`(卡片单选走 FlowBus→updateCheckAllStatus 正常),补同步后实测「已选 3 项」正确 - **`PhoneFilterPanel` 底部按钮被挤出屏幕**:面板高度 wrap_content 且内容插槽无滚动,筛选项多 (出港查询 9 项)时「重置/确认」按钮直接超出屏幕外且无任何报错。修复:内容插槽外包 ScrollView(weight=1),筛选项少时行为不变,超屏时内容区收缩滚动、按钮始终可见 (已回归出港计重 4 项弹层,行为不变) ### 验证 (Verified) +- 提取出库双端验证通过(2026-07-31,Proxyman Map Local mock 口径):手机端菜单入口、 + Tab 角标(双 total)、双形态卡片(含库位空值兜底)、单选/全选与「已选 N 项」联动、 + 出库 ConfirmDialogModel、待出库/已出库两种详情页形态(出库人行按需显隐)、筛选弹层 4 项、 + Tab 切换请求体抓包证实 outState=1 正确携带、冷启动方向恒竖屏、崩溃 0; + 平板端回归:缴费日期默认当天/5 搜索条/全选/底部统计/确认出库与改造前一致,崩溃 0。 + **待内网补测**:outState 过滤 A/B、dlvName=出库人语义、出库真实提交链路 - 进港仓库双端验证通过(2026-07-31,同出港仓库为 Proxyman Map Local mock 口径): 手机端登录→国际 Tab→进港仓库菜单入口、三格统计、三种卡片形态(含空值 "--" 兜底)、 详情 3 Tab 全字段(锁定状态转中文、库位中文姓名、时间截断、空值兜底)、四操作弹框、 diff --git a/CLAUDE.md b/CLAUDE.md index 0481338..64be4e6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1134,6 +1134,13 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = `.checked.set(...)` 会崩溃——接收方 `initOnCreated` 必须对列表 `.map { it.copy() }` 补上。 2026-07-30 review 修正:状态重置弹框改手机底部弹层(弹框双变体首例,见改造步骤第 6 条)、 主列表/回执页补空态、分单浮层补「回执」、分单统计加分母、Tab 角标初始 0 + - 「提取出库」`IntImpPickUpDLVActivity`(module_gjj,类型2 多选批量页 + 手机专属详情新页 + `IntImpPickUpDetailActivity`(Intent 传 Serializable bean 零请求)。待出库/已出库 Tab 绑 + **文档定义入参 `outState`**(0/1,抓包证实携带,效果待内网 #29)+ 角标双 pageQueryTotal; + 双形态卡片按 `isPickedUp`(dlvTime 非空)切换;手机进入时清空平板默认「当天缴费日期」查全量; + 缺口 #28:无 fdate 入参、出参无车牌(提货车辆)/目的港/业务类型。 + ⚠️ 踩坑:`checkAllClick` 全选后底部「已选 N 项」不更新——批量勾选不走 FlowBus 单卡事件, + 必须在 checkAllClick 里同步 selectedCountText) - 「进港仓库」`IntImpStorageUseActivity`(module_gjj,07 出港仓库的进港镜像;**首页菜单实际跳转页, 旧版 `GjjWareHouseActivity` 路由已注释弃用**。差异:卡片/筛选用始发站(fdep 入参)替代目的站; 搜索框「运单号/航班号」分流(含字母→fno、其余→wbNo,抓包证实);筛选 5 项无入参(缺口 #25, @@ -1252,6 +1259,8 @@ adb shell am start -n com.lukouguoji.aerologic/com.lukouguoji.gjc.activity.IntEx | 平板先竖屏再转横屏 + 交互后 UI 放大约 1.6 倍 | Manifest 用了 `@integer/screen_orientation` 资源引用;系统解析 Manifest 不套用限定符,全部取到竖屏值,AutoSize 随之选了平板竖屏 720dp 基准 | Manifest 改回 `unspecified`(见「屏幕方向」小节的 ⛔ 说明) | | Tab/分类切换后列表顶部留一大块空白,卡片数量却不对 | 给 item 根节点加了 `visibility="@{tab条件 ? VISIBLE : GONE}"`——RecyclerView/LinearLayoutManager 不会像普通 ViewGroup 那样让 GONE 的子项自动塌陷为 0 高度,仍按测量高度参与滚动区域计算 | 不要用 item 级 visibility 做过滤;在 ViewModel 里自行维护完整列表,Tab 切换时把过滤后的子集整体 `commonAdapter()?.refresh(filteredList)` 给 adapter | | 通过 `Intent.putExtra(Serializable)` 传递的 Bean,切换其 `checked`/`showMore` 等状态时崩溃 `NullPointerException: ... on a null object reference` | 这些字段标了 `@Transient`(= JVM `transient`,本意是避免 Gson 网络请求序列化 `ObservableBoolean`),但 Java 对象序列化(Intent 传递走的机制)会跳过 `transient` 字段的恢复,反序列化后是 null | 接收方 `initOnCreated` 里对列表做 `.map { it.copy() }`——`.copy()` 会重新走一遍类体初始化逻辑,用全新 `ObservableBoolean(false)` 补上 | +| 布局构建报 `Error: The string "--" is not permitted within comments` | XML 注释中出现连续双横线(如写"兜底 \"--\""),XML 规范禁止 | 注释里改用文字描述(如「兜底双横线」),代码绑定表达式中的 `"--"` 不受影响 | +| 多选页手机版点「全选」后底部「已选 N 项」不更新(单卡勾选正常) | 批量勾选在 `checkAllClick` 里直接 set,不走 FlowBus 的单卡 EVENT_CHECK_CHANGED 事件,`selectedCountText` 只在事件回调里更新 | `checkAllClick` 末尾自行同步 `selectedCountText`(平板布局不绑定该字段,无影响) | --- diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml index dcccdf0..543f109 100644 --- a/app/src/debug/AndroidManifest.xml +++ b/app/src/debug/AndroidManifest.xml @@ -140,5 +140,17 @@ android:exported="true" tools:replace="android:exported" /> + + + + + + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c02e4dd..00d91a6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -558,6 +558,13 @@ android:exported="false" android:screenOrientation="unspecified" /> + + + |+s4M;u>U-6Hx~`s9P1W?& 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 delta 10471 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 CC|zm* diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpPickUpDLVBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpPickUpDLVBean.kt index c51e8bc..7fcef6a 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpPickUpDLVBean.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpPickUpDLVBean.kt @@ -74,4 +74,11 @@ class IntImpPickUpDLVBean : Serializable { var isSelected: Boolean get() = checked.get() set(value) = checked.set(value) + + /** + * 5.5寸手机版:是否已出库(出库时间非空)。 + * 卡片按此切两种形态:待出库(勾选框+橙标签+库位行)/已出库(绿标签+出库人行)。 + */ + val isPickedUp: Boolean + get() = dlvTime.isNotEmpty() } diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpPickUpDLVActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpPickUpDLVActivity.kt index c8fe4e8..ff1e14a 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpPickUpDLVActivity.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpPickUpDLVActivity.kt @@ -13,6 +13,7 @@ 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.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil /** * 国际进港-提取出库 @@ -25,9 +26,12 @@ class IntImpPickUpDLVActivity : override fun viewModelClass() = IntImpPickUpDLVViewModel::class.java override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("国际进港出库") + setBackArrow(if (DeviceUtil.isPhone()) "提取出库" else "国际进港出库") binding.viewModel = viewModel + // 手机形态专属:待出库 Tab 默认态 + 角标计数 + 特码字典(平板不调用,行为零变化) + if (DeviceUtil.isPhone()) viewModel.initPhoneExtras() + // 绑定分页 viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this) diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpPickUpDetailActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpPickUpDetailActivity.kt new file mode 100644 index 0000000..4a00505 --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpPickUpDetailActivity.kt @@ -0,0 +1,45 @@ +package com.lukouguoji.gjj.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.lukouguoji.gjj.R +import com.lukouguoji.gjj.databinding.ActivityIntImpPickUpDetailBinding +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.IntImpPickUpDLVBean +import com.lukouguoji.module_base.common.Constant + +/** + * 国际进港提取出库-运单详情(5.5 寸手机版专属页面) + * + * 设计稿 09_提取出库「查看详情」内嵌页:蓝头运单卡(品名/件重/特码/代理/港站/航班/库位/提货单号) + * + 绿头提货信息卡(柜台办理人/时间,已出库追加出库人/出库时间)。 + * 数据直接复用列表已加载的 bean(Intent 传 Serializable),零新增请求;平板端无入口不可达。 + */ +class IntImpPickUpDetailActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_imp_pick_up_detail + override fun viewModelClass() = BaseViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("运单详情") + val bean = intent.getSerializableExtra(Constant.Key.DATA) as? IntImpPickUpDLVBean + if (bean == null) { + finish() + return + } + binding.bean = bean + } + + companion object { + @JvmStatic + fun start(context: Context, bean: IntImpPickUpDLVBean) { + context.startActivity( + Intent(context, IntImpPickUpDetailActivity::class.java) + .putExtra(Constant.Key.DATA, bean) + ) + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpPickUpDLVViewHolder.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpPickUpDLVViewHolder.kt index 3a28b70..cc1514d 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpPickUpDLVViewHolder.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpPickUpDLVViewHolder.kt @@ -1,6 +1,7 @@ package com.lukouguoji.gjj.holder import android.view.View +import com.lukouguoji.gjj.activity.IntImpPickUpDetailActivity import com.lukouguoji.gjj.databinding.ItemIntImpPickUpDlvBinding import com.lukouguoji.module_base.base.BaseViewHolder import com.lukouguoji.module_base.common.ConstantEvent @@ -9,6 +10,9 @@ import com.lukouguoji.module_base.bean.IntImpPickUpDLVBean /** * 国际进港-提取出库 列表项ViewHolder + * + * 双形态布局:平板变体含 iv_icon(多选图标),手机变体含 iv_check(圆形勾选框,仅待出库形态显示) + * 与 tv_detail(查看详情)。单侧独有的 id 在 Binding 基类中为 @Nullable,必须判空访问。 */ class IntImpPickUpDLVViewHolder(view: View) : BaseViewHolder(view) { @@ -19,11 +23,25 @@ class IntImpPickUpDLVViewHolder(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.ivCheck?.setOnClickListener { + if (!bean.isPickedUp) { + bean.checked.set(!bean.checked.get()) + FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).tryEmit("check_changed") + binding.executePendingBindings() + } + } + + // 手机:查看详情(手机专属新页,数据直接传当前 bean,零新增请求) + binding.tvDetail?.setOnClickListener { + IntImpPickUpDetailActivity.start(itemView.context, bean) + } } } diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpPickUpDLVViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpPickUpDLVViewModel.kt index f5cbe29..ef4d5b4 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpPickUpDLVViewModel.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpPickUpDLVViewModel.kt @@ -20,6 +20,7 @@ import com.lukouguoji.module_base.ktx.formatDate import com.lukouguoji.module_base.ktx.toRequestBody import com.lukouguoji.module_base.model.ConfirmDialogModel import com.lukouguoji.module_base.model.ScanModel +import com.lukouguoji.module_base.util.DictUtils import dev.utils.app.info.KeyValue import dev.utils.common.DateUtils import kotlinx.coroutines.launch @@ -54,6 +55,68 @@ class IntImpPickUpDLVViewModel : BasePageViewModel() { fun updateCheckAllStatus() { val list = pageModel.rv?.commonAdapter()?.items as? List ?: return isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() } + selectedCountText.value = "已选 ${list.count { it.checked.get() }} 项" + } + + // ========== 5.5寸手机版专属 ========== + // 状态 Tab:待出库/已出库(outState 为 pageQuery 真实入参,0:未出库,1:已出库;平板恒空不进请求) + val outState = MutableLiveData("") + val tabList = MutableLiveData(listOf(KeyValue("待出库", "0"), KeyValue("已出库", "1"))) + val tabCounts = MutableLiveData(listOf("0", "0")) + + // 底部操作条「已选 N 项」 + val selectedCountText = MutableLiveData("已选 0 项") + + // 筛选弹层显隐 + val filterVisible = MutableLiveData(false) + + // 筛选条件(flightDate 为 pageQuery 未定义入参 fdate,预留传参,见接口问题清单) + val flightDate = MutableLiveData("") + val flightNo = MutableLiveData("") + + // 特码下拉字典(initPhoneExtras 加载,平板为扫码输入不加载) + val specialCodeList = MutableLiveData>(emptyList()) + + private var phoneExtrasEnabled = false + + /** + * 手机形态专属初始化(Activity 在 DeviceUtil.isPhone() 时调用)。 + * 平板端不调用,请求次数与行为零变化。 + */ + fun initPhoneExtras() { + phoneExtrasEnabled = true + // 默认进「待出库」Tab + outState.value = "0" + // 平板默认按当天缴费日期过滤,设计稿无此默认——手机端清空查全量 + paymentDateStart.value = "" + // 特码字典:flag=1 国际;ieFlag 必须留空 + DictUtils.getSpecialCodeList(addAll = false, flag = 1, ieFlag = "") { list -> + specialCodeList.postValue(listOf(KeyValue("全部", "")) + list) + } + } + + /** 筛选按钮点击 - 打开筛选面板 */ + fun filterClick() { + filterVisible.value = true + } + + /** 关闭筛选面板 */ + fun closeFilter() { + filterVisible.value = false + } + + /** 重置筛选条件 */ + fun resetFilter() { + flightDate.value = "" + flightNo.value = "" + agentCode.value = "" + spCode.value = "" + } + + /** 确认筛选 - 关闭面板并刷新 */ + fun confirmFilter() { + filterVisible.value = false + refresh() } // ========== 适配器配置 ========== @@ -105,6 +168,8 @@ class IntImpPickUpDLVViewModel : BasePageViewModel() { list.forEach { it.checked.set(shouldCheckAll) } isAllChecked.value = shouldCheckAll pageModel.rv?.commonAdapter()?.notifyDataSetChanged() + // 同步手机版底部条「已选 N 项」(平板布局不绑定该字段,无影响) + selectedCountText.value = "已选 ${list.count { it.checked.get() }} 项" } /** @@ -139,12 +204,17 @@ class IntImpPickUpDLVViewModel : BasePageViewModel() { * 获取列表数据 */ override fun getData() { + // 手机专属 3 项平板恒为空,不进请求;fdate 为 pageQuery 未定义入参 + //(后端静默忽略,补齐后自动生效,见接口问题清单) val filterParams = mapOf( "beginDate" to paymentDateStart.value?.ifEmpty { null }, "endDate" to paymentDateEnd.value?.ifEmpty { null }, "agentCode" to agentCode.value?.ifEmpty { null }, "no" to wbNo.value?.ifEmpty { null }, - "spCode" to spCode.value?.ifEmpty { null } + "spCode" to spCode.value?.ifEmpty { null }, + "outState" to outState.value?.ifEmpty { null }, + "fno" to flightNo.value?.ifEmpty { null }, + "fdate" to flightDate.value?.ifEmpty { null } ) val listParams = (filterParams + mapOf( @@ -169,6 +239,28 @@ class IntImpPickUpDLVViewModel : BasePageViewModel() { totalWeight.value = (data?.totalWeight ?: 0.0).toString() } } + + // 手机专属:Tab 角标计数(同条件 + outState=0/1 各查一次,平板不发) + if (phoneExtrasEnabled) { + val pendingParams = (filterParams + mapOf("outState" to "0")).toRequestBody() + launchCollect({ NetApply.api.getIntImpPickUpDLVTotal(pendingParams) }) { + onSuccess = { result -> + tabCounts.value = listOf( + (result.data?.wbNumber ?: 0).toString(), + tabCounts.value?.getOrNull(1) ?: "0" + ) + } + } + val shippedParams = (filterParams + mapOf("outState" to "1")).toRequestBody() + launchCollect({ NetApply.api.getIntImpPickUpDLVTotal(shippedParams) }) { + onSuccess = { result -> + tabCounts.value = listOf( + tabCounts.value?.getOrNull(0) ?: "0", + (result.data?.wbNumber ?: 0).toString() + ) + } + } + } } /** diff --git a/module_gjj/src/main/res/layout-sw600dp/activity_int_imp_pick_up_dlv.xml b/module_gjj/src/main/res/layout-sw600dp/activity_int_imp_pick_up_dlv.xml new file mode 100644 index 0000000..b50335f --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/activity_int_imp_pick_up_dlv.xml @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout-sw600dp/item_int_imp_pick_up_dlv.xml b/module_gjj/src/main/res/layout-sw600dp/item_int_imp_pick_up_dlv.xml new file mode 100644 index 0000000..37fe4b0 --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/item_int_imp_pick_up_dlv.xml @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/activity_int_imp_pick_up_detail.xml b/module_gjj/src/main/res/layout/activity_int_imp_pick_up_detail.xml new file mode 100644 index 0000000..4ee37f8 --- /dev/null +++ b/module_gjj/src/main/res/layout/activity_int_imp_pick_up_detail.xml @@ -0,0 +1,340 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/activity_int_imp_pick_up_dlv.xml b/module_gjj/src/main/res/layout/activity_int_imp_pick_up_dlv.xml index b50335f..1a9be68 100644 --- a/module_gjj/src/main/res/layout/activity_int_imp_pick_up_dlv.xml +++ b/module_gjj/src/main/res/layout/activity_int_imp_pick_up_dlv.xml @@ -1,204 +1,166 @@ + - + + + - + 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"> - - + + + + + + counts="@{viewModel.tabCounts}" + setOnTabChanged="@{()-> viewModel.searchClick()}" + tabs="@{viewModel.tabList}" + value="@={viewModel.outState}" /> - - + + + + + + + + + + + + + + + + + + + + + + + title='@{"代理人"}' + type="@{PhoneDataLayoutType.SPINNER}" + value="@={viewModel.agentCode}" /> - - - - - - - - - - - - - - - + - - - - - - - - + hint='@{"请选择特码"}' + list="@{viewModel.specialCodeList}" + title='@{"特码"}' + type="@{PhoneDataLayoutType.SPINNER}" + value="@={viewModel.spCode}" /> - + - - - - - - - - - - - - - - - - - - - - - + diff --git a/module_gjj/src/main/res/layout/item_int_imp_pick_up_dlv.xml b/module_gjj/src/main/res/layout/item_int_imp_pick_up_dlv.xml index 37fe4b0..f18a006 100644 --- a/module_gjj/src/main/res/layout/item_int_imp_pick_up_dlv.xml +++ b/module_gjj/src/main/res/layout/item_int_imp_pick_up_dlv.xml @@ -1,9 +1,27 @@ + + xmlns:tools="http://schemas.android.com/tools"> + + @@ -17,250 +35,188 @@ android:id="@+id/ll" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginHorizontal="15dp" - android:layout_marginVertical="5dp" - android:background="@drawable/bg_item" - android:gravity="center_vertical" - android:orientation="horizontal" - android:paddingVertical="20dp" - android:paddingHorizontal="10dp"> - - + 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="@{bean.isPickedUp ? @color/phone_text_title : @color/phone_primary}" + android:textSize="16sp" + android:textStyle="bold" + tools:text="78133363573" /> - - + + + + + + + + + android:layout_marginStart="4dp" + android:text="已出库" + android:textColor="@color/phone_text_title" + android:textSize="13sp" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 41412d8..d6309af 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 @@ -78,6 +78,12 @@ class GjViewModel : BaseViewModel() { Constant.AuthName.GjjWareHouseActivity, ARouterConstants.ACTIVITY_URL_GJJ_WARE_HOUSE ), + ActionBean( + "提取出库", + R.drawable.gjj_chu_ku_icon, + Constant.AuthName.IntImpPickUpDLV, + ARouterConstants.ACTIVITY_URL_INT_IMP_PICK_UP_DLV + ), // ULD管理属综合管理业务(Pad 端在「综合管理」菜单组),手机端首页暂无综合 Tab,挂在国际 Tab 下 ActionBean( "ULD管理", diff --git a/module_p/src/main/res/drawable-xxhdpi/gjj_chu_ku_icon.png b/module_p/src/main/res/drawable-xxhdpi/gjj_chu_ku_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7cca5d2ce7f14613e08f3b0a779e2fb4b189d765 GIT binary patch literal 31774 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

    EeYYuFN=HTq<~JjMK#n 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 R@X$AS>+2Y4r)b%2{U6eGS{eWV literal 0 HcmV?d00001 From a33776d959bcc2454b3df718faedb4c41fc5e3d3 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 31 Jul 2026 22:35:56 +0800 Subject: [PATCH 10/29] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E8=BF=9B?= =?UTF-8?q?=E6=B8=AF=E6=9F=A5=E8=AF=A2=E4=B8=8E=E8=BF=9B=E6=B8=AF=E7=A7=BB?= =?UTF-8?q?=E5=BA=93=E9=A1=B5=E9=9D=A25.5=E5=AF=B8=E6=89=8B=E6=9C=BA?= =?UTF-8?q?=E7=AB=AF=E9=80=82=E9=85=8D=EF=BC=88=E8=AE=BE=E8=AE=A1=E7=A8=BF?= =?UTF-8?q?11=E9=A1=B5=E5=85=A8=E9=83=A8=E5=AE=8C=E6=88=90=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 进港查询(10,06出港查询的进港镜像): - IntImpQueryActivity 手机布局:搜索行 + 三格统计(总票数/已入库/已出库客户端计数) + 状态标签卡片(dlvTime/inDate 前端推断)+ 筛选弹层9项(入参全部经api-doc核对存在) - 详情页与运单追踪复用08/06已适配页零新增;平板侧滑筛选面板判空守卫,Pad端零变化 - 修复代理人空值兜底:转换器将JSON null归一为空串致DataBinding `??` 失效, 改用Bean计算属性 agentDisplay(06出港查询同步修正) 进港移库(11,首个后端整模块缺失的设计稿页): - 全新手机专属3页:列表(双Tab+角标/筛选4项/多选批量移库/卡片长按拍照浮层) + 运单详情(三卡片,Intent传bean零请求)+ 拍照上传(复用ImageSelectNewViewHolder, pic/originalPic/picNumber三字段规范) - 后端无IntImpMove模块(api-doc核对),按IntExpMove同名约定预接四接口 + 预定义权限串AppIntImpMove,后端交付后前端零改动生效(缺口#31) 其他:手机首页国际Tab新增进港查询/进港移库入口;新增资源bg_phone_btn_green/ bg_phone_card_header_orange/bg_phone_photo_add/phone_amber;问题清单登记#30~#31; 双端模拟器验证零崩溃(手机Map Local mock全交互链路,平板回归零变化) Co-Authored-By: Claude Fable 5 --- .../skills/phone-adapt/references/api-doc.md | 10 + CHANGELOG.md | 35 ++ CLAUDE.md | 21 + app/src/debug/AndroidManifest.xml | 12 + app/src/main/AndroidManifest.xml | 21 + documents/后端接口对接问题清单.xlsx | Bin 22454 -> 23282 bytes .../lukouguoji/module_base/bean/GjcMaWb.kt | 7 + .../module_base/bean/IntImpMoveBean.kt | 78 +++ .../module_base/bean/IntImpQueryBean.kt | 24 +- .../lukouguoji/module_base/common/Constant.kt | 3 + .../lukouguoji/module_base/http/net/Api.kt | 33 ++ .../module_base/router/ARouterConstants.kt | 1 + .../main/res/drawable/bg_phone_btn_green.xml | 16 + .../drawable/bg_phone_card_header_orange.xml | 9 + .../main/res/drawable/bg_phone_photo_add.xml | 12 + module_base/src/main/res/values/colors.xml | 1 + .../src/main/res/layout/item_gjc_query.xml | 2 +- .../gjj/activity/IntImpMoveActivity.kt | 147 ++++++ .../gjj/activity/IntImpMoveDetailActivity.kt | 46 ++ .../gjj/activity/IntImpMovePhotoActivity.kt | 45 ++ .../gjj/activity/IntImpQueryActivity.kt | 36 +- .../gjj/holder/IntImpMoveViewHolder.kt | 48 ++ .../gjj/holder/IntImpQueryViewHolder.kt | 6 +- .../viewModel/IntImpMoveDetailViewModel.kt | 26 + .../gjj/viewModel/IntImpMovePhotoViewModel.kt | 152 ++++++ .../gjj/viewModel/IntImpMoveViewModel.kt | 187 +++++++ .../gjj/viewModel/IntImpQueryViewModel.kt | 36 ++ .../layout-sw600dp/activity_int_imp_query.xml | 234 +++++++++ .../res/layout-sw600dp/item_int_imp_query.xml | 325 ++++++++++++ .../main/res/layout/activity_int_imp_move.xml | 166 ++++++ .../layout/activity_int_imp_move_detail.xml | 334 ++++++++++++ .../layout/activity_int_imp_move_photo.xml | 123 +++++ .../res/layout/activity_int_imp_query.xml | 437 ++++++++++------ .../src/main/res/layout/item_int_imp_move.xml | 230 +++++++++ .../main/res/layout/item_int_imp_query.xml | 483 +++++++----------- .../sixin/module_p/ui/enter/gj/GjViewModel.kt | 14 + .../res/drawable-xxhdpi/gjj_query_icon.png | Bin 0 -> 32431 bytes 37 files changed, 2884 insertions(+), 476 deletions(-) create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpMoveBean.kt create mode 100644 module_base/src/main/res/drawable/bg_phone_btn_green.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_card_header_orange.xml create mode 100644 module_base/src/main/res/drawable/bg_phone_photo_add.xml create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveActivity.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveDetailActivity.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMovePhotoActivity.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpMoveViewHolder.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveDetailViewModel.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMovePhotoViewModel.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveViewModel.kt create mode 100644 module_gjj/src/main/res/layout-sw600dp/activity_int_imp_query.xml create mode 100644 module_gjj/src/main/res/layout-sw600dp/item_int_imp_query.xml create mode 100644 module_gjj/src/main/res/layout/activity_int_imp_move.xml create mode 100644 module_gjj/src/main/res/layout/activity_int_imp_move_detail.xml create mode 100644 module_gjj/src/main/res/layout/activity_int_imp_move_photo.xml create mode 100644 module_gjj/src/main/res/layout/item_int_imp_move.xml create mode 100644 module_p/src/main/res/drawable-xxhdpi/gjj_query_icon.png diff --git a/.claude/skills/phone-adapt/references/api-doc.md b/.claude/skills/phone-adapt/references/api-doc.md index 93a3cb5..eb54f1b 100644 --- a/.claude/skills/phone-adapt/references/api-doc.md +++ b/.claude/skills/phone-adapt/references/api-doc.md @@ -109,6 +109,16 @@ curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \ 运单号筛选参数名是 **`no`**(平板既有口径);`chargeName`/`chargeTime` = 柜台办理人/缴费(提取)时间, `dlvTime` = 出库时间,`dlvName` 按提货人语义推断作「出库人」展示(待确认 #29); 确认出库接口 `pickUpOut` 文档注明**需将全字段传至后端**(平板 `selectedItems.toRequestBody()` 已满足) +- `IntImpSearch`(进港查询,2026-07-31 文档核对):`pageQuery`/`pageQueryTotal` 分页参数名是 + **`page`/`limit`**(不是 pageNum/pageSize);手机筛选 9 项入参全部真实存在:`beginDate`/`endDate`/ + `fno`/`agentCode`/`spCode`/`origin`(始发站)/`awbType`/`businessType`/`goods`(品名,**不是 goodsCn**); + `outState`(0 未出库/1 已出库)文档为 integer,前端传字符串靠 Jackson 隐式转换;`pageQueryTotal` + 出参无已入库/已出库分项计数(缺口 #30,手机三格统计为客户端计数口径:dlvTime 非空=已出库、 + inDate 非空=已入库);出参含 `agentName`(中文名)+ `agentCode`,agentName 可为 null +- `IntImpMove`(进港移库,2026-07-31 文档核对):**后端整个模块不存在**(api-doc 仅有国内进港 + `DomImpMove` 与国际出港 `IntExpMove`),权限串也没有对应 key(缺口 #31)。前端按 IntExpMove + 同名约定预接 `pageQuery`/`pageQueryTotal`/`move`/`uploadPic` 四接口 + 预定义权限串 + `AppIntImpMove`,后端交付后前端零改动生效 - `IntExpCheckIn`(出港计重,2026-07-29 内网实测):`likeNo` **并非任意模糊**——按 8 位 `no` 匹配(11 位 wbNo 或部分号均 0 条),11 位全号必须走 `wbNo`;`checkIn`/`checkInList` 文档有定义但 `pageQuery`/`pageQueryTotal` **均静默忽略**(缺口 #12,待计重/计重中计数依赖); diff --git a/CHANGELOG.md b/CHANGELOG.md index 94db5db..a358d34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,41 @@ ## [Unreleased] ### 新增 (Added) +- 「进港查询」5.5 寸手机端适配(设计稿 10_进港查询,06 出港查询的进港镜像;详情页与运单追踪 + 复用 08/06 已适配页零新增):列表 `IntImpQueryActivity`(module_gjj,首页菜单实际跳转页; + 旧版 `GjjQueryListActivity` 路由已注释弃用)手机布局 = PhoneSearchBar(运单号+扫码+筛选)+ + 三格统计(总票数/已入库/已出库,已入库/已出库为已加载数据客户端计数,`pageQueryTotal` 无分项 + 出参,缺口 #30)+ 状态标签卡片(前端推断:`dlvTime` 非空=已出库绿 / `inDate` 非空=已入库橙 / + 兜底未入库灰)+ 卡片字段件数(inPc)/重量(inWeight)/代理人/特码;筛选弹层 9 项 + (航班日期起止/航班号/代理/特码/始发站/运单类型/业务类型/品名中,**全部经 api-doc 核对为 + pageQuery 真实入参**,无缺口);平板侧滑筛选面板代码判空守卫,Pad 端行为零变化 +- 「进港移库」5.5 寸手机端全新页面(设计稿 11_进港移库;**首个后端整模块缺失的适配页**: + api-doc 确认无 IntImpMove 模块、权限体系无对应 key,缺口 #31): + `IntImpMoveActivity`(待移库/已移库 Tab + 角标、搜索/扫码、筛选弹层 4 项(航班日期/航班号/ + 特码/运单类型)、多选 + 全选 + 批量移库(ConfirmDialogModel 确认)、卡片长按浮层「拍照」)+ + `IntImpMoveDetailActivity`(运单详情三卡片:蓝头基本信息/绿头移库信息(仅已移库)/橙头异常照片, + Intent 传 bean 零请求)+ `IntImpMovePhotoActivity`(拍照上传:图片网格复用 module_base + `ImageSelectNewViewHolder`,提交走 pic/originalPic/picNumber 三字段规范); + 接口按 IntExpMove 同名约定预接四个(pageQuery/pageQueryTotal/move/uploadPic),权限串 + `AppIntImpMove` 预定义,后端交付后前端零改动生效(权限串下发前手机首页无入口,debug 直启验证) +- 新增 `IntImpMoveBean`(镜像 GjcMove + 航班/照片字段 + isMoved/flightInfo/orDash 计算属性); + `IntImpQueryBean` 新增 isQueryOutbound/isQueryStored/orDash/agentDisplay 计算属性; + 手机首页「国际」Tab 增加「进港查询」(图标 gjj_query_icon)与「进港移库」(图标复用 + gjc_yi_ku_icon)入口 +- 新增手机版资源:`bg_phone_btn_green`(绿色主按钮)、`bg_phone_card_header_orange`(橙色详情卡 + 表头)、`bg_phone_photo_add`(虚线加号槽位)、色值 `phone_amber` + +### 修复 (Fixed) +- 出港查询/进港查询卡片「代理人」空值兜底失效:转换器把 JSON null 归一成空串,DataBinding + `??` 只判 null 不判空串导致 agentCode 回退永不生效;改用 Bean 计算属性 `agentDisplay` + (isNullOrEmpty 双兜底),已同步修正 06 出港查询(`item_gjc_query.xml`) + +### 验证 (Verified) +- 进港查询手机端:Map Local mock 验证三格统计计数、三种状态标签、空值 "--" 兜底、筛选弹层 + 9 项收缩滚动;平板端回归横排搜索条/侧滑筛选面板/底部统计栏零变化;全程崩溃数 0 +- 进港移库手机端:Map Local mock 验证双 Tab 角标、双形态卡片、单选/全选联动计数、空选拦截、 + 移库确认弹框、长按拍照浮层、运单详情、拍照上传页;全程崩溃数 0(后端模块缺失,接口联调待 + 后端交付,见问题清单 #31) - 「提取出库」5.5 寸手机端适配(设计稿 09_提取出库):列表 `IntImpPickUpDLVActivity`(module_gjj) 手机布局 = PhoneSearchBar(运单号+扫码+筛选)+ **PhoneStatusTab 待出库/已出库**(`outState` 为 pageQuery 文档定义入参 0/1,Tab 真实过滤 + 角标双 pageQueryTotal,抓包证实携带)+ diff --git a/CLAUDE.md b/CLAUDE.md index 64be4e6..fdefd92 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1066,6 +1066,8 @@ DataBinding 适配器统一放在 `PhoneWidgetKtx.kt`(同名属性按控件类 9 个筛选项曾把「重置/确认」挤出屏幕)。 出港仓库追加:`bg_phone_btn_disabled`(灰底禁用按钮,与 `bg_phone_btn_weak` 同 10dp 圆角, 卡片操作按钮禁用态配 `phone_tag_gray_text` 文字)。 +进港移库追加:`bg_phone_btn_green`(绿色主按钮,拍照上传「确认提交」)、`bg_phone_card_header_orange` +(橙色详情卡表头,异常照片)、`bg_phone_photo_add`(虚线加号槽位)、色值 `phone_amber`。 ⚠️ **弹层与浮动按钮的层级**:`PhoneFilterPanel` 默认无 elevation,页面里有带 elevation 的浮动按钮(FAB)时 会穿透到弹层之上——给弹层实例加 `android:elevation="8dp"`(大于 FAB 的 6dp)。 @@ -1141,6 +1143,22 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = 缺口 #28:无 fdate 入参、出参无车牌(提货车辆)/目的港/业务类型。 ⚠️ 踩坑:`checkAllClick` 全选后底部「已选 N 项」不更新——批量勾选不走 FlowBus 单卡事件, 必须在 checkAllClick 里同步 selectedCountText) + - 「进港查询」`IntImpQueryActivity`(module_gjj;06 出港查询的进港镜像:三格统计 + 总票数/已入库/已出库为已加载数据客户端计数(`pageQueryTotal` 无分项出参,缺口 #30), + 卡片状态前端推断:`dlvTime` 非空=已出库(绿)/`inDate` 非空=已入库(橙)/兜底未入库(灰); + 筛选弹层 9 项**入参全部经 api-doc 核对真实存在**(分页参数名 `page`/`limit`,品名参数名 + `goods`);详情页与运单追踪复用 08/06 已适配页零新增;平板侧滑筛选面板代码已判空守卫。 + ⚠️ 踩坑:代理人绑定不能写 `bean.agentName ?? bean.agentCode`——转换器把 JSON null 归一成 + 空串,`??` 只判 null 不判空串,须用 Bean 计算属性 `agentDisplay`(06 出港查询同步修正)) + - 「进港移库」`IntImpMoveActivity` + `IntImpMoveDetailActivity` + `IntImpMovePhotoActivity` + (module_gjj,**首个后端整模块缺失的设计稿页**:api-doc 确认无 IntImpMove 模块、权限串无 + 对应 key(缺口 #31)。前端按设计稿完整实现、按 IntExpMove 同名约定预接 + pageQuery/pageQueryTotal/move/uploadPic + 预定义权限串 `AppIntImpMove`,后端交付后零改动 + 生效;权限串下发前手机首页无入口,debug 直启验证。结构镜像 05 出港移库(Tab/批量移库/筛选 + 4 项),新增交互:卡片长按浮层「拍照」(复用 04 运抵的 actionMenuVisible 模式)→ 拍照上传页 + (图片网格复用 module_base `ImageSelectNewViewHolder`,提交走 pic/originalPic/picNumber + 三字段规范);详情页三卡片:基本信息/移库信息(仅已移库)/异常照片。手机专属新页无平板变体, + 布局只放 `res/layout/`;UI 与交互已用 Proxyman Map Local mock 全量验证) - 「进港仓库」`IntImpStorageUseActivity`(module_gjj,07 出港仓库的进港镜像;**首页菜单实际跳转页, 旧版 `GjjWareHouseActivity` 路由已注释弃用**。差异:卡片/筛选用始发站(fdep 入参)替代目的站; 搜索框「运单号/航班号」分流(含字母→fno、其余→wbNo,抓包证实);筛选 5 项无入参(缺口 #25, @@ -1165,8 +1183,10 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = 双变体首例:手机竖排时间线由 Activity `buildVerticalSteps` 动态构建,平板横向步骤条不动; 手机标题按形态切「运单追踪」)。平板侧滑筛选面板代码已判空守卫(手机变体无 filter_panel include,Binding 字段为 @Nullable) +- ✅ **设计稿 11 个入口(01~11)已于 2026-07-31 全部适配完成** - ⏳ **待办**: - `PhoneSearchBar` 接入 AutoQuery 联想(`AutoQueryManager` 目前只对接了 Pad 系组件) + - 进港移库待后端交付 IntImpMove 模块(四接口 + 权限串 AppIntImpMove,缺口 #31)后联调 - 出库交接 Tab 角标恒 0:`IntExpOutHandover/pageQueryTotal` 出参恒 0(后端缺陷,问题清单 #6), 后端修复后角标自动恢复(`handoverState` 过滤本身已于 2026-07-29 实机验证通过)生效 - 📋 **接口对接**:适配中发现的后端接口缺口统一记录在 `documents/后端接口对接问题清单.xlsx` @@ -1261,6 +1281,7 @@ adb shell am start -n com.lukouguoji.aerologic/com.lukouguoji.gjc.activity.IntEx | 通过 `Intent.putExtra(Serializable)` 传递的 Bean,切换其 `checked`/`showMore` 等状态时崩溃 `NullPointerException: ... on a null object reference` | 这些字段标了 `@Transient`(= JVM `transient`,本意是避免 Gson 网络请求序列化 `ObservableBoolean`),但 Java 对象序列化(Intent 传递走的机制)会跳过 `transient` 字段的恢复,反序列化后是 null | 接收方 `initOnCreated` 里对列表做 `.map { it.copy() }`——`.copy()` 会重新走一遍类体初始化逻辑,用全新 `ObservableBoolean(false)` 补上 | | 布局构建报 `Error: The string "--" is not permitted within comments` | XML 注释中出现连续双横线(如写"兜底 \"--\""),XML 规范禁止 | 注释里改用文字描述(如「兜底双横线」),代码绑定表达式中的 `"--"` 不受影响 | | 多选页手机版点「全选」后底部「已选 N 项」不更新(单卡勾选正常) | 批量勾选在 `checkAllClick` 里直接 set,不走 FlowBus 的单卡 EVENT_CHECK_CHANGED 事件,`selectedCountText` 只在事件回调里更新 | `checkAllClick` 末尾自行同步 `selectedCountText`(平板布局不绑定该字段,无影响) | +| XML 里 `bean.a ?? bean.b` 兜底不生效,字段明明有值却显示占位符 | 网络层转换器把 JSON null 归一成空串 `""`,DataBinding 的 `??` 只判 null 不判空串,永远取到左侧的空串 | 在 Bean 上加计算属性做 `isNullOrEmpty` 双兜底(如 `agentDisplay`),XML 绑计算属性(进港查询/出港查询代理人已踩过) | --- diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml index 543f109..8717d8c 100644 --- a/app/src/debug/AndroidManifest.xml +++ b/app/src/debug/AndroidManifest.xml @@ -152,5 +152,17 @@ android:exported="true" tools:replace="android:exported" /> + + + + + + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 00d91a6..2a9b492 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -565,6 +565,27 @@ android:exported="false" android:screenOrientation="unspecified" /> + + + + + + + + + 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 delta 9535 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

    w+8?%v+MQHn=2~&kY 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 + /** + * 国际进港移库-分页查询 + * 接口路径: /IntImpMove/pageQuery + * ⚠️ 后端暂无该模块(2026-07-31 api-doc 核对),按 IntExpMove 命名约定预接,已登记问题清单 + */ + @POST("IntImpMove/pageQuery") + suspend fun getIntImpMoveList(@Body data: RequestBody): BaseListBean + + /** + * 国际进港移库-分页合计 + * 接口路径: /IntImpMove/pageQueryTotal + * ⚠️ 后端暂无该模块,同上 + */ + @POST("IntImpMove/pageQueryTotal") + suspend fun getIntImpMoveTotal(@Body data: RequestBody): BaseResultBean + + /** + * 国际进港移库-批量移库 + * 接口路径: /IntImpMove/move + * ⚠️ 后端暂无该模块,同上 + */ + @POST("IntImpMove/move") + suspend fun submitIntImpMove(@Body data: RequestBody): BaseResultBean + + /** + * 国际进港移库-异常照片上传(pic/originalPic/picNumber 三字段规范) + * 接口路径: /IntImpMove/uploadPic + * ⚠️ 后端暂无该模块,同上 + */ + @POST("IntImpMove/uploadPic") + suspend fun submitIntImpMovePic(@Body data: RequestBody): BaseResultBean + /** * 国际出港库位操作-清仓 * 接口路径: /IntExpStorageUse/updateClear 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 700b17f..1a87ea1 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 @@ -182,6 +182,7 @@ object ARouterConstants { const val ACTIVITY_URL_INT_IMP_LOADING_LIST = "/gjj/IntImpLoadingListActivity" //国际进港 装机单(分拣理货) const val ACTIVITY_URL_INT_IMP_TALLY = "/gjj/IntImpTallyActivity" //国际进港 理货报告 const val ACTIVITY_URL_INT_IMP_PICK_UP_DLV = "/gjj/IntImpPickUpDLVActivity" //国际进港 提取出库 + const val ACTIVITY_URL_INT_IMP_MOVE = "/gjj/IntImpMoveActivity" //国际进港 进港移库(5.5寸手机端专属页) const val ACTIVITY_URL_INT_IMP_ACCIDENT_VISA = "/gjj/IntImpAccidentVisaActivity" //国际进港 事故签证 ///////////////// 航班查询模块 diff --git a/module_base/src/main/res/drawable/bg_phone_btn_green.xml b/module_base/src/main/res/drawable/bg_phone_btn_green.xml new file mode 100644 index 0000000..d868fee --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_btn_green.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_card_header_orange.xml b/module_base/src/main/res/drawable/bg_phone_card_header_orange.xml new file mode 100644 index 0000000..d9abdd0 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_card_header_orange.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_photo_add.xml b/module_base/src/main/res/drawable/bg_phone_photo_add.xml new file mode 100644 index 0000000..a8ff1e7 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_photo_add.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/module_base/src/main/res/values/colors.xml b/module_base/src/main/res/values/colors.xml index 074da37..a369cd7 100644 --- a/module_base/src/main/res/values/colors.xml +++ b/module_base/src/main/res/values/colors.xml @@ -79,5 +79,6 @@ #6366F1 #FEF3C7 #D97706 + #F59E0B \ No newline at end of file diff --git a/module_gjc/src/main/res/layout/item_gjc_query.xml b/module_gjc/src/main/res/layout/item_gjc_query.xml index def293b..f41cdc7 100644 --- a/module_gjc/src/main/res/layout/item_gjc_query.xml +++ b/module_gjc/src/main/res/layout/item_gjc_query.xml @@ -189,7 +189,7 @@ android:layout_weight="1" android:ellipsize="end" android:maxLines="1" - android:text='@{"代理人:" + bean.orDash(bean.agentName ?? bean.agentCode)}' + android:text='@{"代理人:" + bean.orDash(bean.agentDisplay)}' android:textColor="@color/phone_text_body" android:textSize="13sp" tools:text="代理人:中外运" /> diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveActivity.kt new file mode 100644 index 0000000..6642ad0 --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveActivity.kt @@ -0,0 +1,147 @@ +package com.lukouguoji.gjj.activity + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.databinding.ObservableBoolean +import com.alibaba.android.arouter.facade.annotation.Route +import com.lukouguoji.gjj.R +import com.lukouguoji.gjj.databinding.ActivityIntImpMoveBinding +import com.lukouguoji.gjj.viewModel.IntImpMoveViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.IntImpMoveBean +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.common.ConstantEvent +import com.lukouguoji.module_base.impl.FlowBus +import com.lukouguoji.module_base.impl.observe +import com.lukouguoji.module_base.ktx.addOnItemClickListener +import com.lukouguoji.module_base.ktx.showToast +import com.lukouguoji.module_base.model.ConfirmDialogModel +import com.lukouguoji.module_base.model.ScanModel +import com.lukouguoji.module_base.router.ARouterConstants + +/** + * 国际进港-进港移库(5.5 寸手持端专属页面,无平板版本) + * + * 结构镜像 IntExpMoveActivity(国际出港移库),另有卡片长按「拍照」浮层(设计稿新增交互)。 + * ⚠️ 后端目前没有 IntImpMove 模块,接口按同名约定预接(问题清单已登记)。 + */ +@Route(path = ARouterConstants.ACTIVITY_URL_INT_IMP_MOVE) +class IntImpMoveActivity : BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_imp_move + + override fun viewModelClass() = IntImpMoveViewModel::class.java + + /** 筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ + val filterPanelVisible = ObservableBoolean(false) + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("进港移库") + binding.viewModel = viewModel + binding.activity = this + + viewModel.initDictLists() + + viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this) + binding.rv.addOnItemClickListener(viewModel) + + // 监听item选择变化事件,更新全选状态 + FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { + viewModel.onItemCheckChanged() + } + + // 监听刷新事件 + FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) { + viewModel.refresh() + } + + viewModel.refresh() + } + + /** + * 扫码运单号 + */ + fun scanWaybill() { + ScanModel.startScan(this, Constant.RequestCode.WAYBILL) + } + + // ==================== 筛选弹层 ==================== + + fun toggleFilterPanel() { + filterPanelVisible.set(!filterPanelVisible.get()) + } + + /** + * 筛选:重置(只清空弹层内条件,不影响 Tab 与顶部搜索框) + */ + fun resetFilter() { + viewModel.flightDate.value = "" + viewModel.flightNo.value = "" + viewModel.spCode.value = "" + viewModel.awbType.value = "" + } + + fun confirmFilter() { + filterPanelVisible.set(false) + viewModel.searchClick() + } + + // ==================== 卡片长按「拍照」浮层 ==================== + + /** 卡片长按:展开操作浮层(View.OnLongClickListener 要求返回 Boolean) */ + fun showCardActionPhone(bean: IntImpMoveBean): Boolean { + bean.actionMenuVisible.set(true) + return true + } + + /** 点浮层空白处关闭 */ + fun hideCardActionPhone(bean: IntImpMoveBean) { + bean.actionMenuVisible.set(false) + } + + /** 浮层「拍照」→ 拍照上传页 */ + fun openPhoto(bean: IntImpMoveBean) { + bean.actionMenuVisible.set(false) + IntImpMovePhotoActivity.start(this, bean) + } + + /** + * 显示移库确认对话框(底部操作条 setOnActionClick 调用) + */ + fun showMoveConfirmDialog() { + val selectedItems = viewModel.getSelectedItems() + + if (selectedItems.isEmpty()) { + showToast("请至少选择一条运单") + return + } + + ConfirmDialogModel( + message = "确定要移库选中的 ${selectedItems.size} 条运单吗?", + title = "移库确认" + ) { + viewModel.submitMove() + }.show() + } + + /** + * 扫码回调 + */ + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == Constant.RequestCode.WAYBILL && resultCode == Activity.RESULT_OK) { + val code = data?.getStringExtra(Constant.Result.CODED_CONTENT) + viewModel.waybillNo.value = code + viewModel.searchClick() + } + } + + companion object { + @JvmStatic + fun start(context: Context) { + context.startActivity(Intent(context, IntImpMoveActivity::class.java)) + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveDetailActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveDetailActivity.kt new file mode 100644 index 0000000..183ac90 --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveDetailActivity.kt @@ -0,0 +1,46 @@ +package com.lukouguoji.gjj.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.google.gson.Gson +import com.lukouguoji.gjj.R +import com.lukouguoji.gjj.databinding.ActivityIntImpMoveDetailBinding +import com.lukouguoji.gjj.viewModel.IntImpMoveDetailViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.IntImpMoveBean +import com.lukouguoji.module_base.common.Constant + +/** + * 国际进港移库「运单详情」(5.5 寸手持端专属页面) + * + * 由列表卡片的「查看详情」进入;「异常照片」卡片的加号槽位跳拍照上传页。 + */ +class IntImpMoveDetailActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_imp_move_detail + override fun viewModelClass() = IntImpMoveDetailViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("运单详情") + binding.viewModel = viewModel + binding.activity = this + viewModel.initOnCreated(intent) + } + + /** 「异常照片」加号槽位 → 拍照上传页 */ + fun openPhoto() { + viewModel.dataBean.value?.let { IntImpMovePhotoActivity.start(this, it) } + } + + companion object { + @JvmStatic + fun start(context: Context, bean: IntImpMoveBean) { + context.startActivity( + Intent(context, IntImpMoveDetailActivity::class.java) + .putExtra(Constant.Key.DATA, Gson().toJson(bean)) + ) + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMovePhotoActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMovePhotoActivity.kt new file mode 100644 index 0000000..40aba03 --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMovePhotoActivity.kt @@ -0,0 +1,45 @@ +package com.lukouguoji.gjj.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.google.gson.Gson +import com.lukouguoji.gjj.R +import com.lukouguoji.gjj.databinding.ActivityIntImpMovePhotoBinding +import com.lukouguoji.gjj.viewModel.IntImpMovePhotoViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.IntImpMoveBean +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.ktx.addOnItemClickListener + +/** + * 国际进港移库「拍照上传」(5.5 寸手持端专属页面) + * + * 由列表卡片长按浮层「拍照」或运单详情「异常照片」加号槽位进入。 + */ +class IntImpMovePhotoActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_imp_move_photo + override fun viewModelClass() = IntImpMovePhotoViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("拍照上传") + binding.viewModel = viewModel + + viewModel.rv = binding.rv + binding.rv.addOnItemClickListener(viewModel) + + viewModel.initOnCreated(intent) + } + + companion object { + @JvmStatic + fun start(context: Context, bean: IntImpMoveBean) { + context.startActivity( + Intent(context, IntImpMovePhotoActivity::class.java) + .putExtra(Constant.Key.DATA, Gson().toJson(bean)) + ) + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpQueryActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpQueryActivity.kt index f10c084..5d5a28f 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpQueryActivity.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpQueryActivity.kt @@ -19,6 +19,7 @@ import com.lukouguoji.module_base.ktx.getLifecycleOwner import com.lukouguoji.module_base.ktx.setUpperCaseAlphanumericFilter import com.lukouguoji.module_base.ktx.setUpperCaseLetterFilter import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil /** * 国际进港查询列表页 @@ -50,22 +51,35 @@ class IntImpQueryActivity : viewModel.initSpecialCodeList() viewModel.initFilterLists() - // 观察筛选面板显示状态 - viewModel.filterVisible.observe(this) { visible -> - if (visible) showFilterPanel() else hideFilterPanel() + // 平板变体才有侧滑筛选面板(filter_panel/filter_overlay 手机变体不存在,Binding 字段为 null) + val padFilterPanel = binding.filterPanel + if (padFilterPanel != null) { + // 观察筛选面板显示状态(滑入/滑出动画) + viewModel.filterVisible.observe(this) { visible -> + if (visible) showFilterPanel() else hideFilterPanel() + } + + // 航班号:大写字母+数字 + padFilterPanel.filterFlightNo.et.setUpperCaseAlphanumericFilter() + // 始发港:仅大写字母 + padFilterPanel.filterOrigin.et.setUpperCaseLetterFilter() + } else { + // 手机变体:PhoneFilterPanel 的显隐由 XML 直接绑定 viewModel.filterVisible,无需动画代码 + binding.phoneFilterFlightNo?.et?.setUpperCaseAlphanumericFilter() + binding.phoneFilterOrigin?.et?.setUpperCaseLetterFilter() } - // 航班号:大写字母+数字 - binding.filterPanel.filterFlightNo.et.setUpperCaseAlphanumericFilter() - // 始发港:仅大写字母 - binding.filterPanel.filterOrigin.et.setUpperCaseLetterFilter() + // 手机形态专属:已入库/已出库统计计数 + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } viewModel.refresh() } private fun showFilterPanel() { - val panel = binding.filterPanel.root - val overlay = binding.filterOverlay + val panel = binding.filterPanel?.root ?: return + val overlay = binding.filterOverlay ?: return val panelWidth = window.decorView.width / 3 panel.layoutParams = (panel.layoutParams as FrameLayout.LayoutParams).apply { @@ -87,8 +101,8 @@ class IntImpQueryActivity : } private fun hideFilterPanel() { - val panel = binding.filterPanel.root - val overlay = binding.filterOverlay + val panel = binding.filterPanel?.root ?: return + val overlay = binding.filterOverlay ?: return if (panel.visibility != View.VISIBLE) return diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpMoveViewHolder.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpMoveViewHolder.kt new file mode 100644 index 0000000..20aa602 --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpMoveViewHolder.kt @@ -0,0 +1,48 @@ +package com.lukouguoji.gjj.holder + +import android.view.View +import com.lukouguoji.gjj.activity.IntImpMoveActivity +import com.lukouguoji.gjj.activity.IntImpMoveDetailActivity +import com.lukouguoji.gjj.databinding.ItemIntImpMoveBinding +import com.lukouguoji.module_base.base.BaseViewHolder +import com.lukouguoji.module_base.bean.IntImpMoveBean +import com.lukouguoji.module_base.common.ConstantEvent +import com.lukouguoji.module_base.impl.FlowBus +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch + +/** + * 国际进港移库列表项 ViewHolder(5.5 寸手持端专属页面) + * + * 卡片交互: + * · 勾选框点击 → 切换选中并通知 Activity 更新全选/已选计数 + * · 「查看详情」→ 运单详情页 + * · 卡片长按 → 「拍照」操作浮层(XML 绑定 activity 回调) + */ +class IntImpMoveViewHolder(view: View) : + BaseViewHolder(view) { + + override fun onBind(item: Any?, position: Int) { + val bean = getItemBean(item) ?: return + binding.bean = bean + binding.position = position + binding.activity = itemView.context as? IntImpMoveActivity + + // 「查看详情」→ 运单详情页 + binding.llDetail.setOnClickListener { + IntImpMoveDetailActivity.start(itemView.context, bean) + } + + // 勾选框点击 - 切换选择状态 + binding.ivIcon.setOnClickListener { + bean.checked.set(!bean.checked.get()) + binding.executePendingBindings() + + GlobalScope.launch { + FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).emit("check_changed") + } + } + + binding.executePendingBindings() + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpQueryViewHolder.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpQueryViewHolder.kt index 5c618c7..67bd5dc 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpQueryViewHolder.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpQueryViewHolder.kt @@ -19,9 +19,9 @@ class IntImpQueryViewHolder(view: View) : // 注册整行点击事件 notifyItemClick(position, binding.ll) - // 侧滑菜单 - 修改按钮 - binding.btnEdit.setOnClickListener { - binding.swipeMenu.quickClose() + // 侧滑菜单 - 修改按钮(平板变体独有;手机变体无侧滑编辑入口,字段为 null) + binding.btnEdit?.setOnClickListener { + binding.swipeMenu?.quickClose() clickListener?.onItemClick(position, 2000) // type=2000表示修改操作 } } diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveDetailViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveDetailViewModel.kt new file mode 100644 index 0000000..9154f69 --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveDetailViewModel.kt @@ -0,0 +1,26 @@ +package com.lukouguoji.gjj.viewModel + +import android.content.Intent +import androidx.lifecycle.MutableLiveData +import com.google.gson.Gson +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.IntImpMoveBean +import com.lukouguoji.module_base.common.Constant + +/** + * 国际进港移库「运单详情」ViewModel(5.5 寸手持端专属页面) + * + * 列表项数据已包含详情页所需全部字段,故直接由列表带入,不额外请求接口 + * (后端暂无 IntImpMove 模块,也没有 detail 接口可查,问题清单已登记)。 + */ +class IntImpMoveDetailViewModel : BaseViewModel() { + + val dataBean = MutableLiveData(IntImpMoveBean()) + + fun initOnCreated(intent: Intent) { + val json = intent.getStringExtra(Constant.Key.DATA).orEmpty() + if (json.isNotEmpty()) { + dataBean.value = Gson().fromJson(json, IntImpMoveBean::class.java) + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMovePhotoViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMovePhotoViewModel.kt new file mode 100644 index 0000000..98a4cdd --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMovePhotoViewModel.kt @@ -0,0 +1,152 @@ +package com.lukouguoji.gjj.viewModel + +import android.content.Intent +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import androidx.recyclerview.widget.RecyclerView +import com.google.gson.Gson +import com.lukouguoji.gjj.R +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.FileBean +import com.lukouguoji.module_base.bean.IntImpMoveBean +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.http.net.NetApply +import com.lukouguoji.module_base.impl.ImageSelectNewViewHolder +import com.lukouguoji.module_base.interfaces.IOnItemClickListener +import com.lukouguoji.module_base.ktx.commonAdapter +import com.lukouguoji.module_base.ktx.launchLoadingCollect +import com.lukouguoji.module_base.ktx.noNull +import com.lukouguoji.module_base.ktx.showToast +import com.lukouguoji.module_base.ktx.toRequestBody +import com.lukouguoji.module_base.util.MediaUtil +import com.lukouguoji.module_base.util.UploadUtil +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.asFlow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onCompletion +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.onStart + +/** + * 国际进港移库「拍照上传」ViewModel(5.5 寸手持端专属页面) + * + * 图片选择/预览/删除复用 module_base 的 ImageSelectNewViewHolder(末位加号槽位)。 + * 提交走三字段规范(pic 缩略图 / originalPic 原图 / picNumber 数量)。 + * ⚠️ 后端暂无 IntImpMove 模块,提交接口按约定预接(问题清单已登记)。 + */ +class IntImpMovePhotoViewModel : BaseViewModel(), IOnItemClickListener { + + val dataBean = MutableLiveData(IntImpMoveBean()) + + // 图片网格适配器配置(复用公共图片选择组件) + val itemViewHolder = ImageSelectNewViewHolder::class.java + val itemLayoutId = com.lukouguoji.module_base.R.layout.item_image_select_new + + var rv: RecyclerView? = null + + fun initOnCreated(intent: Intent) { + val json = intent.getStringExtra(Constant.Key.DATA).orEmpty() + if (json.isNotEmpty()) { + dataBean.value = Gson().fromJson(json, IntImpMoveBean::class.java) + } + + // 已有照片回填(pic 缩略图 + originalPic 原图),末位补加号槽位 + val bean = dataBean.value ?: IntImpMoveBean() + val picList = bean.pic.split(",").filter { it.isNotEmpty() } + val originalList = bean.originalPic.split(",").filter { it.isNotEmpty() } + val images = picList.mapIndexed { index, picUrl -> + FileBean( + path = MediaUtil.fillUrl(picUrl), + url = picUrl, + originalPic = MediaUtil.fillUrl(originalList.getOrElse(index) { picUrl }) + ) + } + rv?.post { + rv?.commonAdapter()?.refresh(images + FileBean()) + } + } + + /** + * 确认提交:先补传未上传的本地图片,再按三字段规范提交 + */ + fun submitClick() { + (rv?.commonAdapter()?.items ?: emptyList()) + .asFlow() + .map { it as FileBean } + .filter { it.path.isNotEmpty() && it.url.isEmpty() } + .onEach { + val data = UploadUtil.upload(it.path).data + // UploadUtil 返回:newName=原图(较大),zipFileName=缩略图(较小) + it.url = data?.zipFileName ?: "" + it.originalPic = data?.newName ?: "" + } + .flowOn(Dispatchers.IO) + .onStart { showLoading() } + .catch { + showToast(it.message.noNull("上传图片失败")) + dismissLoading() + } + .onCompletion { + launchLoadingCollect({ + val list = (rv?.commonAdapter()?.items ?: emptyList()) + .filterIsInstance() + .filter { it.path.isNotEmpty() } + val bean = dataBean.value!! + bean.picNumber = list.size.toString() + bean.pic = list.joinToString(",") { MediaUtil.removeUrl(it.url) } + bean.originalPic = list.joinToString(",") { MediaUtil.removeUrl(it.originalPic) } + + NetApply.api.submitIntImpMovePic(bean.toRequestBody()) + }) { + onSuccess = { + showToast("提交成功") + getTopActivity().finish() + } + onFailed = { _, msg -> + showToast(msg.noNull("提交失败")) + } + } + } + .launchIn(viewModelScope) + } + + /** + * 「拍照/上传」按钮:直接唤起图片选择(含拍照入口) + */ + fun pickClick() { + MediaUtil.pickImage(getTopActivity(), maxNum = 9) { results -> + val adapter = rv?.commonAdapter() ?: return@pickImage + results.forEach { result -> + // 在加号槽位(最后一项)之前插入 + val insertPos = (adapter.items.size - 1).coerceAtLeast(0) + adapter.items.add(insertPos, FileBean(path = result.realPath)) + adapter.notifyItemInserted(insertPos) + } + } + } + + /** + * 图片网格点击回调(长按出删除角标 / 点删除角标移除) + */ + override fun onItemClick(position: Int, type: Int) { + val adapter = rv?.commonAdapter() ?: return + val bean = adapter.getItem(position) as? FileBean ?: return + when (type) { + com.lukouguoji.module_base.R.id.rl -> { + if (bean.path.isNotEmpty()) { + bean.canDelete.set(!bean.canDelete.get()) + } + } + + com.lukouguoji.module_base.R.id.iv_delete -> { + adapter.removeItem(position) + } + + else -> {} + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveViewModel.kt new file mode 100644 index 0000000..e9bb2de --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveViewModel.kt @@ -0,0 +1,187 @@ +package com.lukouguoji.gjj.viewModel + +import androidx.lifecycle.MutableLiveData +import com.lukouguoji.gjj.R +import com.lukouguoji.gjj.holder.IntImpMoveViewHolder +import com.lukouguoji.module_base.base.BasePageViewModel +import com.lukouguoji.module_base.bean.IntImpMoveBean +import com.lukouguoji.module_base.http.net.NetApply +import com.lukouguoji.module_base.interfaces.IOnItemClickListener +import com.lukouguoji.module_base.ktx.commonAdapter +import com.lukouguoji.module_base.ktx.launchCollect +import com.lukouguoji.module_base.ktx.launchLoadingCollect +import com.lukouguoji.module_base.ktx.noNull +import com.lukouguoji.module_base.ktx.showToast +import com.lukouguoji.module_base.ktx.toRequestBody +import com.lukouguoji.module_base.util.CheckUtil +import com.lukouguoji.module_base.util.DictUtils +import dev.utils.app.info.KeyValue + +/** + * 国际进港移库 ViewModel(5.5 寸手持端专属页面,无平板版本) + * + * 结构镜像 IntExpMoveViewModel(国际出港移库)。 + * ⚠️ 后端目前没有 IntImpMove 模块(2026-07-31 api-doc 核对),接口按同名约定预接, + * 实机会请求失败(问题清单已登记),后端交付后自动生效。 + */ +class IntImpMoveViewModel : BasePageViewModel(), IOnItemClickListener { + + // ========== 搜索字段(设计稿筛选弹层:航班日期 / 航班号 / 特码 / 运单类型) ========== + val flightDate = MutableLiveData("") // 航班日期 + val flightNo = MutableLiveData("") // 航班号 + val spCode = MutableLiveData("") // 特码 + val awbType = MutableLiveData("") // 运单类型 + val moveState = MutableLiveData("0") // 移库状态(默认「待移库」Tab) + val waybillNo = MutableLiveData("") // 运单号 + + // ========== 下拉数据 ========== + val spCodeList = MutableLiveData>(emptyList()) + val awbTypeList = MutableLiveData>(emptyList()) + + /** 状态 Tab 配置(设计稿只有两个 Tab,无「全部」) */ + val moveStateTabs = MutableLiveData( + listOf(KeyValue("待移库", "0"), KeyValue("已移库", "1")) + ) + + /** 状态 Tab 角标(与 [moveStateTabs] 等长) */ + val moveStateCounts = MutableLiveData(listOf("", "")) + + /** 已选数量(底部操作条「已选 N 项」) */ + val selectedCount = MutableLiveData("0") + + // ========== 全选状态 ========== + val isAllChecked = MutableLiveData(false) + + // ========== 适配器配置 ========== + val itemViewHolder = IntImpMoveViewHolder::class.java + val itemLayoutId = R.layout.item_int_imp_move + + /** + * 初始化下拉字典(特码 + 运单类型,type=II 国际进港) + */ + fun initDictLists() { + // flag=1 国际;ieFlag 必须留空——传值后端返回空数组(与既有国际页面口径一致) + DictUtils.getSpecialCodeList(addAll = false, flag = 1, ieFlag = "") { list -> + spCodeList.postValue(listOf(KeyValue("全部", "")) + list) + } + DictUtils.getWaybillTypeList(type = "II", addAll = true) { + awbTypeList.postValue(it) + } + } + + fun searchClick() { + refresh() + } + + /** + * 全选/取消全选 + */ + fun toggleSelectAll() { + val adapter = pageModel.rv?.commonAdapter() ?: return + val list = adapter.items.filterIsInstance() + + CheckUtil.handleAllCheck(list) + updateCheckAllStatus() + adapter.notifyDataSetChanged() + } + + /** + * 更新全选状态与已选计数 + */ + fun updateCheckAllStatus() { + val adapter = pageModel.rv?.commonAdapter() ?: return + val list = adapter.items.filterIsInstance() + + isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() } + selectedCount.value = list.count { it.checked.get() }.toString() + } + + /** + * 单个item选择变化时调用(从Activity接收事件) + */ + fun onItemCheckChanged() { + updateCheckAllStatus() + } + + /** + * 获取选中的运单 + */ + fun getSelectedItems(): List { + val adapter = pageModel.rv?.commonAdapter() ?: return emptyList() + return adapter.items.filterIsInstance().filter { it.checked.get() } + } + + /** + * 提交移库(在Activity中显示确认对话框后调用) + */ + fun submitMove() { + val selectedItems = getSelectedItems() + + if (selectedItems.isEmpty()) { + showToast("请至少选择一条运单") + return + } + + launchLoadingCollect({ NetApply.api.submitIntImpMove(selectedItems.toRequestBody()) }) { + onSuccess = { + showToast("移库成功") + refresh() + } + onFailed = { _, msg -> + showToast(msg.noNull("移库失败")) + } + } + } + + /** + * 获取列表数据 + */ + override fun getData() { + // 构建筛选参数(只传递非空值;参数名按 IntExpMove 同名约定,待后端交付核对) + val filterParams = mutableMapOf() + + flightDate.value?.takeIf { it.isNotEmpty() }?.let { filterParams["fdate"] = it } + flightNo.value?.takeIf { it.isNotEmpty() }?.let { filterParams["fno"] = it } + spCode.value?.takeIf { it.isNotEmpty() }?.let { filterParams["spCode"] = it } + awbType.value?.takeIf { it.isNotEmpty() }?.let { filterParams["awbType"] = it } + moveState.value?.takeIf { it.isNotEmpty() }?.let { filterParams["moveState"] = it } + waybillNo.value?.takeIf { it.isNotEmpty() }?.let { filterParams["wbNo"] = it } + + val listParams = (filterParams + mapOf( + "pageNum" to pageModel.page, + "pageSize" to pageModel.limit + )).toRequestBody() + + launchLoadingCollect({ NetApply.api.getIntImpMoveList(listParams) }) { + onSuccess = { + pageModel.handleListBean(it) { updateCheckAllStatus() } + } + } + + // Tab 角标计数(复用统计接口,moveState=0/1 各查一次) + loadTabCounts(filterParams) + } + + private fun loadTabCounts(filterParams: Map) { + listOf("0", "1").forEachIndexed { index, state -> + val params = (filterParams + mapOf("moveState" to state)).toRequestBody() + launchCollect({ NetApply.api.getIntImpMoveTotal(params) }) { + onSuccess = { result -> + val count = (result.data?.wbNumber ?: 0).toString() + val current = moveStateCounts.value?.toMutableList() ?: mutableListOf("", "") + if (index < current.size) { + current[index] = count + moveStateCounts.value = current + } + } + } + } + } + + /** + * Item点击事件处理(点击已在ViewHolder中处理) + */ + override fun onItemClick(position: Int, type: Int) { + // 卡片交互均在 ViewHolder / XML 中处理 + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpQueryViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpQueryViewModel.kt index c23da61..2dd1708 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpQueryViewModel.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpQueryViewModel.kt @@ -64,6 +64,24 @@ class IntImpQueryViewModel : BasePageViewModel(), IOnItemClickListener { val awbTypeList = MutableLiveData>(emptyList()) val businessTypeList = MutableLiveData>(emptyList()) + // ==================== 5.5寸手机版专属 ==================== + // 三格统计:已入库 / 已出库(总票数复用 totalCount,为服务端全量口径) + // pageQueryTotal 无分项统计出参——已入库/已出库为「已加载数据」客户端计数口径, + // 与卡片状态标签同一判定(dlvTime / inDate,见 IntImpQueryBean) + val storedCount = MutableLiveData("0") + val outboundCount = MutableLiveData("0") + + private var phoneExtrasEnabled = false + private var phoneLoadedList: List = emptyList() + + /** + * 手机形态专属初始化(Activity 在 DeviceUtil.isPhone() 时调用)。 + * 平板端不调用,请求次数与行为零变化。 + */ + fun initPhoneExtras() { + phoneExtrasEnabled = true + } + // ==================== 筛选条件 ==================== val spCode = MutableLiveData("") val flightNo = MutableLiveData("") @@ -165,6 +183,14 @@ class IntImpQueryViewModel : BasePageViewModel(), IOnItemClickListener { }) { onSuccess = { pageInfo -> pageModel.handleListBean(pageInfo.toBaseListBean()) + + // 手机三格统计:对已加载数据做客户端计数(平板不触发) + if (phoneExtrasEnabled) { + val pageItems = pageInfo.list ?: emptyList() + phoneLoadedList = + if (pageModel.page <= 1) pageItems else phoneLoadedList + pageItems + updatePhoneCounts() + } } } @@ -180,6 +206,16 @@ class IntImpQueryViewModel : BasePageViewModel(), IOnItemClickListener { } } + /** + * 手机三格统计(已入库/已出库):与卡片状态标签同一判定口径(dlvTime / inDate), + * 统计范围为已加载的列表数据。 + */ + private fun updatePhoneCounts() { + outboundCount.value = phoneLoadedList.count { it.isQueryOutbound }.toString() + storedCount.value = + phoneLoadedList.count { !it.isQueryOutbound && it.isQueryStored }.toString() + } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (resultCode == Activity.RESULT_OK && data != null) { when (requestCode) { diff --git a/module_gjj/src/main/res/layout-sw600dp/activity_int_imp_query.xml b/module_gjj/src/main/res/layout-sw600dp/activity_int_imp_query.xml new file mode 100644 index 0000000..ab0223b --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/activity_int_imp_query.xml @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout-sw600dp/item_int_imp_query.xml b/module_gjj/src/main/res/layout-sw600dp/item_int_imp_query.xml new file mode 100644 index 0000000..5fd2b42 --- /dev/null +++ b/module_gjj/src/main/res/layout-sw600dp/item_int_imp_query.xml @@ -0,0 +1,325 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/activity_int_imp_move.xml b/module_gjj/src/main/res/layout/activity_int_imp_move.xml new file mode 100644 index 0000000..c650e7c --- /dev/null +++ b/module_gjj/src/main/res/layout/activity_int_imp_move.xml @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/activity_int_imp_move_detail.xml b/module_gjj/src/main/res/layout/activity_int_imp_move_detail.xml new file mode 100644 index 0000000..1f3d243 --- /dev/null +++ b/module_gjj/src/main/res/layout/activity_int_imp_move_detail.xml @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/activity_int_imp_move_photo.xml b/module_gjj/src/main/res/layout/activity_int_imp_move_photo.xml new file mode 100644 index 0000000..2b6a422 --- /dev/null +++ b/module_gjj/src/main/res/layout/activity_int_imp_move_photo.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/activity_int_imp_query.xml b/module_gjj/src/main/res/layout/activity_int_imp_query.xml index ab0223b..093968d 100644 --- a/module_gjj/src/main/res/layout/activity_int_imp_query.xml +++ b/module_gjj/src/main/res/layout/activity_int_imp_query.xml @@ -1,205 +1,201 @@ + + - + + - + android:background="@color/phone_page_bg"> - - - - - + android:layout_height="match_parent" + android:orientation="vertical"> - + + + + android:layout_height="wrap_content" + android:background="@color/white" + android:orientation="vertical" + android:paddingHorizontal="16dp" + android:paddingTop="16dp" + android:paddingBottom="12dp"> - - + + + + + + + + - - + - - - - - - - - - - - - - + android:orientation="vertical" + android:paddingHorizontal="12dp" + android:paddingVertical="10dp"> - + - - - - - - - + - - - - - - - - + + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="10dp" + android:layout_weight="1" + android:background="@drawable/bg_phone_card" + android:orientation="horizontal"> + + + android:orientation="vertical" + android:paddingHorizontal="12dp" + android:paddingVertical="10dp"> + android:text="已入库" + android:textColor="@color/phone_text_body" + android:textSize="12sp" /> + tools:text="2" /> + + + + + + + + + + + + + + tools:text="2" /> @@ -207,28 +203,131 @@ - - + + android:layout_height="0dp" + android:layout_weight="1"> - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - diff --git a/module_gjj/src/main/res/layout/item_int_imp_move.xml b/module_gjj/src/main/res/layout/item_int_imp_move.xml new file mode 100644 index 0000000..38d6bdb --- /dev/null +++ b/module_gjj/src/main/res/layout/item_int_imp_move.xml @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/item_int_imp_query.xml b/module_gjj/src/main/res/layout/item_int_imp_query.xml index 5fd2b42..241864a 100644 --- a/module_gjj/src/main/res/layout/item_int_imp_query.xml +++ b/module_gjj/src/main/res/layout/item_int_imp_query.xml @@ -1,325 +1,226 @@ + + + + - - - - - - - - - - + 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_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="6dp" + android:text='@{"件数:" + (bean.inPc != null ? String.valueOf(bean.inPc) : "--")}' + android:textColor="@color/phone_text_body" + android:textSize="13sp" + tools:text="件数:444" /> - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 d6309af..2348421 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 @@ -78,6 +78,20 @@ class GjViewModel : BaseViewModel() { Constant.AuthName.GjjWareHouseActivity, ARouterConstants.ACTIVITY_URL_GJJ_WARE_HOUSE ), + // 进港移库:后端暂无该模块与权限串 AppIntImpMove(问题清单已登记), + // 权限串下发前此入口不会显示;实机验证走 debug 直启 + ActionBean( + "进港移库", + R.drawable.gjc_yi_ku_icon, // 复用出港移库图标(Pad 端无进港移库菜单) + Constant.AuthName.IntImpMove, + ARouterConstants.ACTIVITY_URL_INT_IMP_MOVE + ), + ActionBean( + "进港查询", + R.drawable.gjj_query_icon, + Constant.AuthName.GjjQueryListActivity, + ARouterConstants.ACTIVITY_URL_GJJ_QUERY_LIST + ), ActionBean( "提取出库", R.drawable.gjj_chu_ku_icon, diff --git a/module_p/src/main/res/drawable-xxhdpi/gjj_query_icon.png b/module_p/src/main/res/drawable-xxhdpi/gjj_query_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0e98155bb88ebfb32e2ee8fc614c558e5b2f97fa GIT binary patch literal 32431 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 LdW0Oj<$?bJtqHOv literal 0 HcmV?d00001 From eb0655d3fc747c3eab3438a810f046436c52b8b4 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 31 Jul 2026 23:12:14 +0800 Subject: [PATCH 11/29] =?UTF-8?q?fix:=2011=E6=A8=A1=E5=9D=97=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E7=A8=BF=E5=85=A8=E9=87=8F=E8=B5=B0=E6=9F=A5=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=E2=80=94=E2=80=94=E6=97=B6=E9=97=B4=E7=BA=BF=E7=8A=B6?= =?UTF-8?q?=E6=80=81pill/=E6=89=8B=E6=9C=BA=E7=9F=AD=E6=A0=87=E9=A2=98/ULD?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E9=A1=BA=E5=BA=8F/=E8=AE=A1=E9=87=8D?= =?UTF-8?q?=E5=8D=A1=E7=89=87=E5=9B=BE=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 设计稿逐态渲染对照走查(01~11 全模块)后的修正: - 运单追踪竖排时间线为已发生节点补状态pill(绿底展示该环节日志content,超长省略) - 11 页手机端标题按设计稿改短标题(DeviceUtil.isPhone 分支,平板长标题零变化): 出库交接/出港待计重/计重记录/计重明细/开始计重/出港运抵/出港移库/出港查询/ 出港货物/进港查询/进港货物 - ULD 编辑表单「来源」移至「所在港」之后(设计稿顺序) - 出港计重列表卡片与计重记录卡片补字段小图标(airplane/location/person/tag) 接口缺口台账复核:#31 进港移库整模块缺失成立(api-doc 全模块清单+报价单双重印证); #19 修正定性——IntExpArrive/declare 入参已含收发货人全套字段,改登记为待确认提交口径; #10 成立(单条 deleteUld 在、批量无)。 双端抽验:手机短标题三页生效(出港待计重/出库交接/进港货物),平板保持长标题,零崩溃。 Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 8 + .../page/log/detail/LogDetailActivity.kt | 35 +- app/src/main/res/layout/activity_uld_edit.xml | 22 +- documents/后端接口对接问题清单.xlsx | Bin 23282 -> 23556 bytes .../gjc/activity/GjcQueryActivity.kt | 2 +- .../gjc/activity/GjcQueryDetailsActivity.kt | 181 +++---- .../gjc/activity/GjcWeighingListActivity.kt | 210 ++++----- .../GjcWeighingRecordDetailsActivity.kt | 207 ++++---- .../activity/GjcWeighingRecordListActivity.kt | 198 ++++---- .../gjc/activity/GjcWeighingStartActivity.kt | 442 +++++++++--------- .../gjc/activity/IntExpArriveActivity.kt | 354 +++++++------- .../gjc/activity/IntExpOutHandoverActivity.kt | 2 +- .../gjc/page/move/IntExpMoveActivity.kt | 342 +++++++------- .../src/main/res/layout/item_gjc_weighing.xml | 99 +++- .../res/layout/item_gjc_weighing_record.xml | 26 +- .../gjj/activity/IntImpQueryActivity.kt | 2 +- .../activity/IntImpQueryDetailsActivity.kt | 3 +- 17 files changed, 1124 insertions(+), 1009 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a358d34..9ea617b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,14 @@ 表头)、`bg_phone_photo_add`(虚线加号槽位)、色值 `phone_amber` ### 修复 (Fixed) +- 【11 模块全量设计稿走查】修正 4 类差异(2026-07-31,3 个并行审计 + 逐态渲染比对): + ① 运单追踪手机竖排时间线补齐已发生节点的状态 pill(绿底标签展示该环节日志 content, + 如「放行状态:01」,超长省略,设计稿 06/08 运单追踪均有此元素); + ② 11 个页面手机端标题对齐设计稿短标题(出库交接/出港待计重/计重记录/计重明细/开始计重/ + 出港运抵/出港移库/出港查询/出港货物/进港查询/进港货物),平板保持原长标题零变化; + ③ ULD 编辑表单「来源」字段移至「所在港」之后(设计稿顺序); + ④ 出港计重列表卡片(日期/航程/代理/特码)与计重记录卡片(代理)补齐字段小图标 + (复用 ic_phone_airplane/location/person/tag,与其余模块卡片风格统一) - 出港查询/进港查询卡片「代理人」空值兜底失效:转换器把 JSON null 归一成空串,DataBinding `??` 只判 null 不判空串导致 agentCode 回退永不生效;改用 Bean 计算属性 `agentDisplay` (isNullOrEmpty 双兜底),已同步修正 06 出港查询(`item_gjc_query.xml`) diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/log/detail/LogDetailActivity.kt b/app/src/main/java/com/lukouguoji/aerologic/page/log/detail/LogDetailActivity.kt index 9214019..0a80fc9 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/log/detail/LogDetailActivity.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/log/detail/LogDetailActivity.kt @@ -91,7 +91,9 @@ class LogDetailActivity : BaseBindingActivity - - - + + + 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 { - - override fun layoutId() = R.layout.activity_gjc_query_details - override fun viewModelClass() = GjcQueryDetailsViewModel::class.java - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("国际出港查询详情") - binding.viewModel = viewModel - - // 初始化ViewModel(传入maWbId) - viewModel.initOnCreated(intent) - - // 配置ViewPager2 - binding.vp.adapter = CustomVP2Adapter( - viewModel.fragmentList, - supportFragmentManager, - lifecycle - ) - binding.vp.isUserInputEnabled = false // 禁用滑动 - binding.vp.offscreenPageLimit = 3 // 预加载3个Fragment - - // 监听Tab索引变化,切换Fragment - viewModel.currentTab.observe(this) { - binding.vp.setCurrentItem(it, false) // false:无动画 - } - - // 标题栏右侧添加日志查询图标 - val toolbar = findViewById(com.lukouguoji.module_base.R.id.toolbar) - val logIcon = ImageView(this).apply { - setImageResource(com.lukouguoji.module_base.R.drawable.img_log) - layoutParams = Toolbar.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ).apply { - gravity = Gravity.END or Gravity.CENTER_VERTICAL - marginEnd = 15 - width = 30.dp - height = 30.dp - } - setOnClickListener { - val wbNo = viewModel.maWbData.value?.get("wbNo") as? String ?: "" - ARouter.getInstance() - .build(ARouterConstants.ACTIVITY_URL_LOG_DETAIL) - .withString(Constant.Key.KEY, wbNo) - .withString(Constant.Key.AWB_TYPE, "IO") - .navigation() - } - } - toolbar.addView(logIcon) - - // 加载详情数据 - viewModel.loadDetails() - } - - private val Int.dp: Int - get() = (this * resources!!.displayMetrics.density).toInt() - - companion object { - @JvmStatic - fun start(context: Context, maWbId: Long?) { - val starter = Intent(context, GjcQueryDetailsActivity::class.java) - .putExtra(Constant.Key.ID, maWbId?.toString() ?: "") - context.startActivity(starter) - } - } -} +package com.lukouguoji.gjc.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.Gravity +import android.widget.ImageView +import android.widget.LinearLayout +import androidx.appcompat.widget.Toolbar +import com.alibaba.android.arouter.facade.annotation.Route +import com.alibaba.android.arouter.launcher.ARouter +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityGjcQueryDetailsBinding +import com.lukouguoji.gjc.viewModel.GjcQueryDetailsViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.base.CustomVP2Adapter +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil + +/** + * 国际出港查询详情页面 + */ +@Route(path = ARouterConstants.ACTIVITY_URL_GJC_QUERY_DETAILS) +class GjcQueryDetailsActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_gjc_query_details + override fun viewModelClass() = GjcQueryDetailsViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow(if (DeviceUtil.isPhone()) "出港货物" else "国际出港查询详情") + binding.viewModel = viewModel + + // 初始化ViewModel(传入maWbId) + viewModel.initOnCreated(intent) + + // 配置ViewPager2 + binding.vp.adapter = CustomVP2Adapter( + viewModel.fragmentList, + supportFragmentManager, + lifecycle + ) + binding.vp.isUserInputEnabled = false // 禁用滑动 + binding.vp.offscreenPageLimit = 3 // 预加载3个Fragment + + // 监听Tab索引变化,切换Fragment + viewModel.currentTab.observe(this) { + binding.vp.setCurrentItem(it, false) // false:无动画 + } + + // 标题栏右侧添加日志查询图标 + val toolbar = findViewById(com.lukouguoji.module_base.R.id.toolbar) + val logIcon = ImageView(this).apply { + setImageResource(com.lukouguoji.module_base.R.drawable.img_log) + layoutParams = Toolbar.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ).apply { + gravity = Gravity.END or Gravity.CENTER_VERTICAL + marginEnd = 15 + width = 30.dp + height = 30.dp + } + setOnClickListener { + val wbNo = viewModel.maWbData.value?.get("wbNo") as? String ?: "" + ARouter.getInstance() + .build(ARouterConstants.ACTIVITY_URL_LOG_DETAIL) + .withString(Constant.Key.KEY, wbNo) + .withString(Constant.Key.AWB_TYPE, "IO") + .navigation() + } + } + toolbar.addView(logIcon) + + // 加载详情数据 + viewModel.loadDetails() + } + + private val Int.dp: Int + get() = (this * resources!!.displayMetrics.density).toInt() + + companion object { + @JvmStatic + fun start(context: Context, maWbId: Long?) { + val starter = Intent(context, GjcQueryDetailsActivity::class.java) + .putExtra(Constant.Key.ID, maWbId?.toString() ?: "") + context.startActivity(starter) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt index f657b23..b10a91e 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt @@ -1,105 +1,105 @@ -package com.lukouguoji.gjc.activity - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import androidx.databinding.ObservableBoolean -import com.alibaba.android.arouter.facade.annotation.Route -import com.lukouguoji.gjc.R -import com.lukouguoji.gjc.databinding.ActivityGjcWeighingListBinding -import com.lukouguoji.gjc.viewModel.GjcWeighingViewModel -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.bean.GjcWeighingBean -import com.lukouguoji.module_base.common.ConstantEvent -import com.lukouguoji.module_base.impl.FlowBus -import com.lukouguoji.module_base.impl.observe -import com.lukouguoji.module_base.ktx.getLifecycleOwner -import com.lukouguoji.module_base.router.ARouterConstants -import com.lukouguoji.module_base.util.DeviceUtil - -/** - * 国际出港计重列表页 - * - * 布局 id 不区分设备,平板/手机由资源限定符自动选择: - * layout-sw600dp/activity_gjc_weighing_list.xml(平板) - * layout/activity_gjc_weighing_list.xml(手机) - */ -@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_LIST) -class GjcWeighingListActivity : - BaseBindingActivity() { - - override fun layoutId() = R.layout.activity_gjc_weighing_list - - override fun viewModelClass() = GjcWeighingViewModel::class.java - - /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ - val filterPanelVisible = ObservableBoolean(false) - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("国际出港待计重") - - binding.viewModel = viewModel - binding.activity = this - - // 手机版专属数据:放开默认日期、加载筛选弹层字典、启用三格统计 - // 平板端不调用,查询链路与请求次数与改造前完全一致 - if (DeviceUtil.isPhone()) { - viewModel.initPhoneExtras() - } - - // 初始化代理人列表(从API获取) - viewModel.initAgentList() - - // 初始化特码列表(从API获取) - viewModel.initSpecialCodeList() - - // 绑定分页逻辑 - viewModel.pageModel - .bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner()) - - // 监听刷新事件 - FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { viewModel.onItemCheckChanged() } - - FlowBus.with(ConstantEvent.EVENT_REFRESH) - .observe(this) { - viewModel.refresh() - } - - // 初始加载 - viewModel.refresh() - } - - // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 字段) ==================== - - /** 手机版筛选弹层显隐切换 */ - fun toggleFilterPanel() { - filterPanelVisible.set(!filterPanelVisible.get()) - } - - /** 手机版筛选:重置(只清弹层内条件,不影响顶部搜索框) */ - fun resetFilter() { - viewModel.channelFilter.value = "" - viewModel.carrierFilter.value = "" - viewModel.awbTypeFilter.value = "" - viewModel.agentCode.value = "" - } - - /** 手机版筛选:确认 */ - fun confirmFilter() { - filterPanelVisible.set(false) - viewModel.searchClick() - } - - /** 手机版卡片内「提前运抵」(单票,由 ViewHolder 调用) */ - fun preArriveClick(bean: GjcWeighingBean) { - viewModel.arrivedAheadSingle(bean) - } - - companion object { - @JvmStatic - fun start(context: Context) { - val starter = Intent(context, GjcWeighingListActivity::class.java) - context.startActivity(starter) - } - } -} +package com.lukouguoji.gjc.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.databinding.ObservableBoolean +import com.alibaba.android.arouter.facade.annotation.Route +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityGjcWeighingListBinding +import com.lukouguoji.gjc.viewModel.GjcWeighingViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.GjcWeighingBean +import com.lukouguoji.module_base.common.ConstantEvent +import com.lukouguoji.module_base.impl.FlowBus +import com.lukouguoji.module_base.impl.observe +import com.lukouguoji.module_base.ktx.getLifecycleOwner +import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil + +/** + * 国际出港计重列表页 + * + * 布局 id 不区分设备,平板/手机由资源限定符自动选择: + * layout-sw600dp/activity_gjc_weighing_list.xml(平板) + * layout/activity_gjc_weighing_list.xml(手机) + */ +@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_LIST) +class GjcWeighingListActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_gjc_weighing_list + + override fun viewModelClass() = GjcWeighingViewModel::class.java + + /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ + val filterPanelVisible = ObservableBoolean(false) + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow(if (DeviceUtil.isPhone()) "出港待计重" else "国际出港待计重") + + binding.viewModel = viewModel + binding.activity = this + + // 手机版专属数据:放开默认日期、加载筛选弹层字典、启用三格统计 + // 平板端不调用,查询链路与请求次数与改造前完全一致 + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } + + // 初始化代理人列表(从API获取) + viewModel.initAgentList() + + // 初始化特码列表(从API获取) + viewModel.initSpecialCodeList() + + // 绑定分页逻辑 + viewModel.pageModel + .bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner()) + + // 监听刷新事件 + FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { viewModel.onItemCheckChanged() } + + FlowBus.with(ConstantEvent.EVENT_REFRESH) + .observe(this) { + viewModel.refresh() + } + + // 初始加载 + viewModel.refresh() + } + + // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 字段) ==================== + + /** 手机版筛选弹层显隐切换 */ + fun toggleFilterPanel() { + filterPanelVisible.set(!filterPanelVisible.get()) + } + + /** 手机版筛选:重置(只清弹层内条件,不影响顶部搜索框) */ + fun resetFilter() { + viewModel.channelFilter.value = "" + viewModel.carrierFilter.value = "" + viewModel.awbTypeFilter.value = "" + viewModel.agentCode.value = "" + } + + /** 手机版筛选:确认 */ + fun confirmFilter() { + filterPanelVisible.set(false) + viewModel.searchClick() + } + + /** 手机版卡片内「提前运抵」(单票,由 ViewHolder 调用) */ + fun preArriveClick(bean: GjcWeighingBean) { + viewModel.arrivedAheadSingle(bean) + } + + companion object { + @JvmStatic + fun start(context: Context) { + val starter = Intent(context, GjcWeighingListActivity::class.java) + context.startActivity(starter) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordDetailsActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordDetailsActivity.kt index f2c6887..ca1e9fe 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordDetailsActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordDetailsActivity.kt @@ -1,103 +1,104 @@ -package com.lukouguoji.gjc.activity - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import androidx.recyclerview.widget.DividerItemDecoration -import androidx.recyclerview.widget.LinearLayoutManager -import com.alibaba.android.arouter.facade.annotation.Route -import com.lukouguoji.gjc.R -import com.lukouguoji.gjc.databinding.ActivityGjcWeighingRecordDetailsBinding -import com.lukouguoji.gjc.holder.GjcCheckInRecordViewHolder -import com.lukouguoji.gjc.viewModel.GjcWeighingRecordDetailsViewModel -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.base.CommonAdapter -import com.lukouguoji.module_base.bean.GjcCheckInRecord -import com.lukouguoji.module_base.bean.GjcWeighingRecordBean -import com.lukouguoji.module_base.common.Constant -import com.lukouguoji.module_base.router.ARouterConstants - -/** - * 国际出港计重明细页 - * - * 布局 id 不区分设备,平板/手机由资源限定符自动选择: - * layout-sw600dp/activity_gjc_weighing_record_details.xml(平板,列表内联编辑) - * layout/activity_gjc_weighing_record_details.xml(手机,单条记录经全屏「修改记录」覆层编辑) - */ -@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_DETAILS) -class GjcWeighingRecordDetailsActivity : - BaseBindingActivity() { - - private lateinit var adapter: CommonAdapter - - // 当前编辑模式(供ViewHolder获取) - var currentEditMode = false - - override fun layoutId() = R.layout.activity_gjc_weighing_record_details - - override fun viewModelClass() = GjcWeighingRecordDetailsViewModel::class.java - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("国际出港计重明细") - - binding.viewModel = viewModel - - // 初始化RecyclerView - val layoutManager = LinearLayoutManager(this) - binding.recyclerView.layoutManager = layoutManager - - // 添加分割线 - val divider = DividerItemDecoration(this, DividerItemDecoration.VERTICAL) - binding.recyclerView.addItemDecoration(divider) - - adapter = CommonAdapter( - this, - R.layout.item_gjc_check_in_record, - GjcCheckInRecordViewHolder::class.java - ) - binding.recyclerView.adapter = adapter - - // 监听数据变化更新RecyclerView - viewModel.recordList.observe(this) { records -> - adapter.refresh(records) - } - - // 监听编辑模式变化,更新当前编辑模式并刷新列表 - viewModel.isEditMode.observe(this) { isEditMode -> - // 更新当前编辑模式状态 - currentEditMode = isEditMode - - // 刷新所有可见的 ViewHolder - adapter.notifyDataSetChanged() - } - - // 初始化数据 - viewModel.initOnCreated(intent) - } - - // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 编辑链路) ==================== - - /** - * 手机版:打开「修改记录」覆层编辑指定记录。 - * 复用 [GjcWeighingRecordDetailsViewModel.onModifyClick] 的备份/编辑态逻辑, - * 覆层显隐由 isEditMode 驱动(平板端该状态驱动列表内联编辑,互不影响)。 - */ - fun openPhoneEdit(record: GjcCheckInRecord) { - viewModel.onModifyClick() - binding.editRecord = record - } - - /** 手机版:取消编辑(恢复备份并收起覆层) */ - fun closePhoneEdit() { - viewModel.onCancelClick() - } - - companion object { - @JvmStatic - fun start(context: Context, bean: GjcWeighingRecordBean) { - val starter = Intent(context, GjcWeighingRecordDetailsActivity::class.java) - .putExtra(Constant.Key.BEAN, bean) - context.startActivity(starter) - } - } -} +package com.lukouguoji.gjc.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.LinearLayoutManager +import com.alibaba.android.arouter.facade.annotation.Route +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityGjcWeighingRecordDetailsBinding +import com.lukouguoji.gjc.holder.GjcCheckInRecordViewHolder +import com.lukouguoji.gjc.viewModel.GjcWeighingRecordDetailsViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.base.CommonAdapter +import com.lukouguoji.module_base.bean.GjcCheckInRecord +import com.lukouguoji.module_base.bean.GjcWeighingRecordBean +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil + +/** + * 国际出港计重明细页 + * + * 布局 id 不区分设备,平板/手机由资源限定符自动选择: + * layout-sw600dp/activity_gjc_weighing_record_details.xml(平板,列表内联编辑) + * layout/activity_gjc_weighing_record_details.xml(手机,单条记录经全屏「修改记录」覆层编辑) + */ +@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_DETAILS) +class GjcWeighingRecordDetailsActivity : + BaseBindingActivity() { + + private lateinit var adapter: CommonAdapter + + // 当前编辑模式(供ViewHolder获取) + var currentEditMode = false + + override fun layoutId() = R.layout.activity_gjc_weighing_record_details + + override fun viewModelClass() = GjcWeighingRecordDetailsViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow(if (DeviceUtil.isPhone()) "计重明细" else "国际出港计重明细") + + binding.viewModel = viewModel + + // 初始化RecyclerView + val layoutManager = LinearLayoutManager(this) + binding.recyclerView.layoutManager = layoutManager + + // 添加分割线 + val divider = DividerItemDecoration(this, DividerItemDecoration.VERTICAL) + binding.recyclerView.addItemDecoration(divider) + + adapter = CommonAdapter( + this, + R.layout.item_gjc_check_in_record, + GjcCheckInRecordViewHolder::class.java + ) + binding.recyclerView.adapter = adapter + + // 监听数据变化更新RecyclerView + viewModel.recordList.observe(this) { records -> + adapter.refresh(records) + } + + // 监听编辑模式变化,更新当前编辑模式并刷新列表 + viewModel.isEditMode.observe(this) { isEditMode -> + // 更新当前编辑模式状态 + currentEditMode = isEditMode + + // 刷新所有可见的 ViewHolder + adapter.notifyDataSetChanged() + } + + // 初始化数据 + viewModel.initOnCreated(intent) + } + + // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 编辑链路) ==================== + + /** + * 手机版:打开「修改记录」覆层编辑指定记录。 + * 复用 [GjcWeighingRecordDetailsViewModel.onModifyClick] 的备份/编辑态逻辑, + * 覆层显隐由 isEditMode 驱动(平板端该状态驱动列表内联编辑,互不影响)。 + */ + fun openPhoneEdit(record: GjcCheckInRecord) { + viewModel.onModifyClick() + binding.editRecord = record + } + + /** 手机版:取消编辑(恢复备份并收起覆层) */ + fun closePhoneEdit() { + viewModel.onCancelClick() + } + + companion object { + @JvmStatic + fun start(context: Context, bean: GjcWeighingRecordBean) { + val starter = Intent(context, GjcWeighingRecordDetailsActivity::class.java) + .putExtra(Constant.Key.BEAN, bean) + context.startActivity(starter) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt index bb83248..836ed9c 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt @@ -1,99 +1,99 @@ -package com.lukouguoji.gjc.activity - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import androidx.databinding.ObservableBoolean -import com.alibaba.android.arouter.facade.annotation.Route -import com.lukouguoji.gjc.R -import com.lukouguoji.gjc.databinding.ActivityGjcWeighingRecordListBinding -import com.lukouguoji.gjc.viewModel.GjcWeighingRecordViewModel -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.common.ConstantEvent -import com.lukouguoji.module_base.impl.FlowBus -import com.lukouguoji.module_base.impl.observe -import com.lukouguoji.module_base.ktx.getLifecycleOwner -import com.lukouguoji.module_base.router.ARouterConstants -import com.lukouguoji.module_base.util.DeviceUtil - -/** - * 国际出港计重记录列表页 - * - * 布局 id 不区分设备,平板/手机由资源限定符自动选择: - * layout-sw600dp/activity_gjc_weighing_record_list.xml(平板) - * layout/activity_gjc_weighing_record_list.xml(手机) - */ -@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_LIST) -class GjcWeighingRecordListActivity : - BaseBindingActivity() { - - override fun layoutId() = R.layout.activity_gjc_weighing_record_list - - override fun viewModelClass() = GjcWeighingRecordViewModel::class.java - - /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ - val filterPanelVisible = ObservableBoolean(false) - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("国际出港计重记录") - - binding.viewModel = viewModel - binding.activity = this - - // 手机版专属数据:放开默认日期、加载计重人下拉 - // 平板端不调用,查询链路与请求次数与改造前完全一致 - if (DeviceUtil.isPhone()) { - viewModel.initPhoneExtras() - } - - // 初始化代理人列表 - viewModel.initAgentList() - - // 初始化特码列表 - viewModel.initSpecialCodeList() - - // 绑定分页逻辑 - viewModel.pageModel - .bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner()) - - // 监听刷新事件 - FlowBus.with(ConstantEvent.EVENT_REFRESH) - .observe(this) { - viewModel.refresh() - } - - // 初始加载 - viewModel.refresh() - } - - // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 字段) ==================== - - /** 手机版筛选弹层显隐切换 */ - fun toggleFilterPanel() { - filterPanelVisible.set(!filterPanelVisible.get()) - } - - /** 手机版筛选:重置(只清弹层内条件,不影响顶部搜索框) */ - fun resetFilter() { - viewModel.checkInDateStart.value = "" - viewModel.checkInDateEnd.value = "" - viewModel.agentCode.value = "" - viewModel.spCode.value = "" - viewModel.destFilter.value = "" - viewModel.opUserFilter.value = "" - } - - /** 手机版筛选:确认 */ - fun confirmFilter() { - filterPanelVisible.set(false) - viewModel.searchClick() - } - - companion object { - @JvmStatic - fun start(context: Context) { - val starter = Intent(context, GjcWeighingRecordListActivity::class.java) - context.startActivity(starter) - } - } -} +package com.lukouguoji.gjc.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.databinding.ObservableBoolean +import com.alibaba.android.arouter.facade.annotation.Route +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityGjcWeighingRecordListBinding +import com.lukouguoji.gjc.viewModel.GjcWeighingRecordViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.common.ConstantEvent +import com.lukouguoji.module_base.impl.FlowBus +import com.lukouguoji.module_base.impl.observe +import com.lukouguoji.module_base.ktx.getLifecycleOwner +import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil + +/** + * 国际出港计重记录列表页 + * + * 布局 id 不区分设备,平板/手机由资源限定符自动选择: + * layout-sw600dp/activity_gjc_weighing_record_list.xml(平板) + * layout/activity_gjc_weighing_record_list.xml(手机) + */ +@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_LIST) +class GjcWeighingRecordListActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_gjc_weighing_record_list + + override fun viewModelClass() = GjcWeighingRecordViewModel::class.java + + /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ + val filterPanelVisible = ObservableBoolean(false) + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow(if (DeviceUtil.isPhone()) "计重记录" else "国际出港计重记录") + + binding.viewModel = viewModel + binding.activity = this + + // 手机版专属数据:放开默认日期、加载计重人下拉 + // 平板端不调用,查询链路与请求次数与改造前完全一致 + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } + + // 初始化代理人列表 + viewModel.initAgentList() + + // 初始化特码列表 + viewModel.initSpecialCodeList() + + // 绑定分页逻辑 + viewModel.pageModel + .bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner()) + + // 监听刷新事件 + FlowBus.with(ConstantEvent.EVENT_REFRESH) + .observe(this) { + viewModel.refresh() + } + + // 初始加载 + viewModel.refresh() + } + + // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 字段) ==================== + + /** 手机版筛选弹层显隐切换 */ + fun toggleFilterPanel() { + filterPanelVisible.set(!filterPanelVisible.get()) + } + + /** 手机版筛选:重置(只清弹层内条件,不影响顶部搜索框) */ + fun resetFilter() { + viewModel.checkInDateStart.value = "" + viewModel.checkInDateEnd.value = "" + viewModel.agentCode.value = "" + viewModel.spCode.value = "" + viewModel.destFilter.value = "" + viewModel.opUserFilter.value = "" + } + + /** 手机版筛选:确认 */ + fun confirmFilter() { + filterPanelVisible.set(false) + viewModel.searchClick() + } + + companion object { + @JvmStatic + fun start(context: Context) { + val starter = Intent(context, GjcWeighingRecordListActivity::class.java) + context.startActivity(starter) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingStartActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingStartActivity.kt index 937534d..252b63f 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingStartActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingStartActivity.kt @@ -1,221 +1,221 @@ -package com.lukouguoji.gjc.activity - -import android.animation.Animator -import android.animation.AnimatorListenerAdapter -import android.animation.AnimatorSet -import android.animation.ObjectAnimator -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.view.View -import com.alibaba.android.arouter.facade.annotation.Route -import com.lukouguoji.gjc.R -import com.lukouguoji.gjc.databinding.ActivityGjcWeighingStartBinding -import com.lukouguoji.gjc.viewModel.GjcWeighingStartViewModel -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.common.Constant -import com.lukouguoji.module_base.router.ARouterConstants -import com.lukouguoji.module_base.util.DeviceUtil - -/** - * 国际出港计重-开始计重页面 - */ -@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_START) -class GjcWeighingStartActivity : - BaseBindingActivity() { - - private var isExpanded = false - - override fun layoutId() = R.layout.activity_gjc_weighing_start - - override fun viewModelClass() = GjcWeighingStartViewModel::class.java - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("国际出港开始计重") - binding.viewModel = viewModel - - // 手机版专属:提交体携带托盘数量/托盘自重(平板不调用,请求体与改造前完全一致) - if (DeviceUtil.isPhone()) { - viewModel.initPhoneExtras() - } - - viewModel.initOnCreated(this, intent) - - setupFloatButtons() - } - - private fun setupFloatButtons() { - // 浮动按钮组仅平板布局存在(layout-sw600dp),手机布局无这些 id,直接跳过 - val mainFloatButton = binding.mainFloatButton ?: return - val maskView = binding.maskView ?: return - val subButton1 = binding.subButton1 ?: return - val subButton2 = binding.subButton2 ?: return - - // 主按钮点击事件 - mainFloatButton.setOnClickListener { - if (!isExpanded) { - expandButtons() - } - } - - // 遮罩层点击事件 - maskView.setOnClickListener { - collapseButtons() - } - - // 子按钮1点击事件 - 跳转到出港运抵页面 - subButton1.setOnClickListener { - com.alibaba.android.arouter.launcher.ARouter.getInstance() - .build(ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE) - .navigation() - collapseButtons() - } - - // 子按钮2点击事件 - 跳转到计重记录 - subButton2.setOnClickListener { - com.alibaba.android.arouter.launcher.ARouter.getInstance() - .build(ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_LIST) - .navigation() - collapseButtons() - } - } - - /** - * 展开子按钮(仅平板,手机布局无浮动按钮组) - */ - private fun expandButtons() { - val mainFloatButton = binding.mainFloatButton ?: return - val maskView = binding.maskView ?: return - val subButton1 = binding.subButton1 ?: return - val subButton2 = binding.subButton2 ?: return - - isExpanded = true - - // 显示遮罩层 - maskView.visibility = View.VISIBLE - maskView.alpha = 0f - maskView.animate().alpha(0.3f).setDuration(200).start() - - // 显示子按钮 - subButton1.visibility = View.VISIBLE - subButton2.visibility = View.VISIBLE - - // 子按钮1动画(向左上方移动: 左移15dp, 上移55dp) - val sub1TransX = ObjectAnimator.ofFloat(subButton1, "translationX", 0f, -5f) - val sub1TransY = ObjectAnimator.ofFloat(subButton1, "translationY", 0f, -25f) - val sub1Alpha = ObjectAnimator.ofFloat(subButton1, "alpha", 0f, 1f) - val sub1Scale = ObjectAnimator.ofFloat(subButton1, "scaleX", 0f, 1f) - val sub1ScaleY = ObjectAnimator.ofFloat(subButton1, "scaleY", 0f, 1f) - - val animSet1 = AnimatorSet() - animSet1.playTogether(sub1TransX, sub1TransY, sub1Alpha, sub1Scale, sub1ScaleY) - animSet1.duration = 200 - - // 子按钮2动画(向左下方移动: 左移55dp, 下移15dp) - val sub2TransX = ObjectAnimator.ofFloat(subButton2, "translationX", 0f, -25f) - val sub2TransY = ObjectAnimator.ofFloat(subButton2, "translationY", 0f, -5f) - val sub2Alpha = ObjectAnimator.ofFloat(subButton2, "alpha", 0f, 1f) - val sub2Scale = ObjectAnimator.ofFloat(subButton2, "scaleX", 0f, 1f) - val sub2ScaleY = ObjectAnimator.ofFloat(subButton2, "scaleY", 0f, 1f) - - val animSet2 = AnimatorSet() - animSet2.playTogether(sub2TransX, sub2TransY, sub2Alpha, sub2Scale, sub2ScaleY) - animSet2.duration = 200 - animSet2.startDelay = 50 - - // 主按钮隐藏动画 - mainFloatButton.animate() - .scaleX(0f) - .scaleY(0f) - .alpha(0f) - .setDuration(150) - .setListener(object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation: Animator) { - mainFloatButton.visibility = View.GONE - } - }) - .start() - - animSet1.start() - animSet2.start() - } - - /** - * 收起子按钮(仅平板,手机布局无浮动按钮组) - */ - private fun collapseButtons() { - val mainFloatButton = binding.mainFloatButton ?: return - val maskView = binding.maskView ?: return - val subButton1 = binding.subButton1 ?: return - val subButton2 = binding.subButton2 ?: return - - isExpanded = false - - // 隐藏遮罩层 - maskView.animate().alpha(0f).setDuration(200).withEndAction { - maskView.visibility = View.GONE - }.start() - - // 子按钮1动画(回到原位) - val sub1TransX = ObjectAnimator.ofFloat(subButton1, "translationX", subButton1.translationX, 0f) - val sub1TransY = ObjectAnimator.ofFloat(subButton1, "translationY", subButton1.translationY, 0f) - val sub1Alpha = ObjectAnimator.ofFloat(subButton1, "alpha", 1f, 0f) - val sub1Scale = ObjectAnimator.ofFloat(subButton1, "scaleX", 1f, 0f) - val sub1ScaleY = ObjectAnimator.ofFloat(subButton1, "scaleY", 1f, 0f) - - val animSet1 = AnimatorSet() - animSet1.playTogether(sub1TransX, sub1TransY, sub1Alpha, sub1Scale, sub1ScaleY) - animSet1.duration = 200 - - // 子按钮2动画(回到原位) - val sub2TransX = ObjectAnimator.ofFloat(subButton2, "translationX", subButton2.translationX, 0f) - val sub2TransY = ObjectAnimator.ofFloat(subButton2, "translationY", subButton2.translationY, 0f) - val sub2Alpha = ObjectAnimator.ofFloat(subButton2, "alpha", 1f, 0f) - val sub2Scale = ObjectAnimator.ofFloat(subButton2, "scaleX", 1f, 0f) - val sub2ScaleY = ObjectAnimator.ofFloat(subButton2, "scaleY", 1f, 0f) - - val animSet2 = AnimatorSet() - animSet2.playTogether(sub2TransX, sub2TransY, sub2Alpha, sub2Scale, sub2ScaleY) - animSet2.duration = 200 - - animSet1.addListener(object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation: Animator) { - subButton1.visibility = View.GONE - } - }) - - animSet2.addListener(object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation: Animator) { - subButton2.visibility = View.GONE - } - }) - - // 主按钮显示动画 - mainFloatButton.visibility = View.VISIBLE - mainFloatButton.animate() - .scaleX(1f) - .scaleY(1f) - .alpha(1f) - .setDuration(200) - .setStartDelay(100) - .setListener(null) - .start() - - animSet1.start() - animSet2.start() - } - - companion object { - /** - * 启动开始计重页面 - * @param context 上下文 - * @param maWbId 运单ID,默认为0(新增模式) - */ - @JvmStatic - fun startForAdd(context: Context, maWbId: Long = 0) { - val starter = Intent(context, GjcWeighingStartActivity::class.java) - .putExtra(Constant.Key.MAWB_ID, maWbId) - context.startActivity(starter) - } - } -} +package com.lukouguoji.gjc.activity + +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.animation.AnimatorSet +import android.animation.ObjectAnimator +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.View +import com.alibaba.android.arouter.facade.annotation.Route +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityGjcWeighingStartBinding +import com.lukouguoji.gjc.viewModel.GjcWeighingStartViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil + +/** + * 国际出港计重-开始计重页面 + */ +@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_START) +class GjcWeighingStartActivity : + BaseBindingActivity() { + + private var isExpanded = false + + override fun layoutId() = R.layout.activity_gjc_weighing_start + + override fun viewModelClass() = GjcWeighingStartViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow(if (DeviceUtil.isPhone()) "开始计重" else "国际出港开始计重") + binding.viewModel = viewModel + + // 手机版专属:提交体携带托盘数量/托盘自重(平板不调用,请求体与改造前完全一致) + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } + + viewModel.initOnCreated(this, intent) + + setupFloatButtons() + } + + private fun setupFloatButtons() { + // 浮动按钮组仅平板布局存在(layout-sw600dp),手机布局无这些 id,直接跳过 + val mainFloatButton = binding.mainFloatButton ?: return + val maskView = binding.maskView ?: return + val subButton1 = binding.subButton1 ?: return + val subButton2 = binding.subButton2 ?: return + + // 主按钮点击事件 + mainFloatButton.setOnClickListener { + if (!isExpanded) { + expandButtons() + } + } + + // 遮罩层点击事件 + maskView.setOnClickListener { + collapseButtons() + } + + // 子按钮1点击事件 - 跳转到出港运抵页面 + subButton1.setOnClickListener { + com.alibaba.android.arouter.launcher.ARouter.getInstance() + .build(ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE) + .navigation() + collapseButtons() + } + + // 子按钮2点击事件 - 跳转到计重记录 + subButton2.setOnClickListener { + com.alibaba.android.arouter.launcher.ARouter.getInstance() + .build(ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_LIST) + .navigation() + collapseButtons() + } + } + + /** + * 展开子按钮(仅平板,手机布局无浮动按钮组) + */ + private fun expandButtons() { + val mainFloatButton = binding.mainFloatButton ?: return + val maskView = binding.maskView ?: return + val subButton1 = binding.subButton1 ?: return + val subButton2 = binding.subButton2 ?: return + + isExpanded = true + + // 显示遮罩层 + maskView.visibility = View.VISIBLE + maskView.alpha = 0f + maskView.animate().alpha(0.3f).setDuration(200).start() + + // 显示子按钮 + subButton1.visibility = View.VISIBLE + subButton2.visibility = View.VISIBLE + + // 子按钮1动画(向左上方移动: 左移15dp, 上移55dp) + val sub1TransX = ObjectAnimator.ofFloat(subButton1, "translationX", 0f, -5f) + val sub1TransY = ObjectAnimator.ofFloat(subButton1, "translationY", 0f, -25f) + val sub1Alpha = ObjectAnimator.ofFloat(subButton1, "alpha", 0f, 1f) + val sub1Scale = ObjectAnimator.ofFloat(subButton1, "scaleX", 0f, 1f) + val sub1ScaleY = ObjectAnimator.ofFloat(subButton1, "scaleY", 0f, 1f) + + val animSet1 = AnimatorSet() + animSet1.playTogether(sub1TransX, sub1TransY, sub1Alpha, sub1Scale, sub1ScaleY) + animSet1.duration = 200 + + // 子按钮2动画(向左下方移动: 左移55dp, 下移15dp) + val sub2TransX = ObjectAnimator.ofFloat(subButton2, "translationX", 0f, -25f) + val sub2TransY = ObjectAnimator.ofFloat(subButton2, "translationY", 0f, -5f) + val sub2Alpha = ObjectAnimator.ofFloat(subButton2, "alpha", 0f, 1f) + val sub2Scale = ObjectAnimator.ofFloat(subButton2, "scaleX", 0f, 1f) + val sub2ScaleY = ObjectAnimator.ofFloat(subButton2, "scaleY", 0f, 1f) + + val animSet2 = AnimatorSet() + animSet2.playTogether(sub2TransX, sub2TransY, sub2Alpha, sub2Scale, sub2ScaleY) + animSet2.duration = 200 + animSet2.startDelay = 50 + + // 主按钮隐藏动画 + mainFloatButton.animate() + .scaleX(0f) + .scaleY(0f) + .alpha(0f) + .setDuration(150) + .setListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + mainFloatButton.visibility = View.GONE + } + }) + .start() + + animSet1.start() + animSet2.start() + } + + /** + * 收起子按钮(仅平板,手机布局无浮动按钮组) + */ + private fun collapseButtons() { + val mainFloatButton = binding.mainFloatButton ?: return + val maskView = binding.maskView ?: return + val subButton1 = binding.subButton1 ?: return + val subButton2 = binding.subButton2 ?: return + + isExpanded = false + + // 隐藏遮罩层 + maskView.animate().alpha(0f).setDuration(200).withEndAction { + maskView.visibility = View.GONE + }.start() + + // 子按钮1动画(回到原位) + val sub1TransX = ObjectAnimator.ofFloat(subButton1, "translationX", subButton1.translationX, 0f) + val sub1TransY = ObjectAnimator.ofFloat(subButton1, "translationY", subButton1.translationY, 0f) + val sub1Alpha = ObjectAnimator.ofFloat(subButton1, "alpha", 1f, 0f) + val sub1Scale = ObjectAnimator.ofFloat(subButton1, "scaleX", 1f, 0f) + val sub1ScaleY = ObjectAnimator.ofFloat(subButton1, "scaleY", 1f, 0f) + + val animSet1 = AnimatorSet() + animSet1.playTogether(sub1TransX, sub1TransY, sub1Alpha, sub1Scale, sub1ScaleY) + animSet1.duration = 200 + + // 子按钮2动画(回到原位) + val sub2TransX = ObjectAnimator.ofFloat(subButton2, "translationX", subButton2.translationX, 0f) + val sub2TransY = ObjectAnimator.ofFloat(subButton2, "translationY", subButton2.translationY, 0f) + val sub2Alpha = ObjectAnimator.ofFloat(subButton2, "alpha", 1f, 0f) + val sub2Scale = ObjectAnimator.ofFloat(subButton2, "scaleX", 1f, 0f) + val sub2ScaleY = ObjectAnimator.ofFloat(subButton2, "scaleY", 1f, 0f) + + val animSet2 = AnimatorSet() + animSet2.playTogether(sub2TransX, sub2TransY, sub2Alpha, sub2Scale, sub2ScaleY) + animSet2.duration = 200 + + animSet1.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + subButton1.visibility = View.GONE + } + }) + + animSet2.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + subButton2.visibility = View.GONE + } + }) + + // 主按钮显示动画 + mainFloatButton.visibility = View.VISIBLE + mainFloatButton.animate() + .scaleX(1f) + .scaleY(1f) + .alpha(1f) + .setDuration(200) + .setStartDelay(100) + .setListener(null) + .start() + + animSet1.start() + animSet2.start() + } + + companion object { + /** + * 启动开始计重页面 + * @param context 上下文 + * @param maWbId 运单ID,默认为0(新增模式) + */ + @JvmStatic + fun startForAdd(context: Context, maWbId: Long = 0) { + val starter = Intent(context, GjcWeighingStartActivity::class.java) + .putExtra(Constant.Key.MAWB_ID, maWbId) + context.startActivity(starter) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveActivity.kt index ce5498f..41d7c1f 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveActivity.kt @@ -1,177 +1,177 @@ -package com.lukouguoji.gjc.activity - -import android.app.Activity -import android.content.Intent -import android.os.Bundle -import androidx.databinding.ObservableBoolean -import com.alibaba.android.arouter.facade.annotation.Autowired -import com.alibaba.android.arouter.facade.annotation.Route -import com.alibaba.android.arouter.launcher.ARouter -import com.lukouguoji.gjc.R -import com.lukouguoji.gjc.databinding.ActivityIntExpArriveBinding -import com.lukouguoji.gjc.viewModel.IntExpArriveViewModel -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.bean.GjcHaWb -import com.lukouguoji.module_base.bean.GjcMaWb -import com.lukouguoji.module_base.common.Constant -import com.lukouguoji.module_base.common.ConstantEvent -import com.lukouguoji.module_base.impl.FlowBus -import com.lukouguoji.module_base.impl.observe -import com.lukouguoji.module_base.ktx.addOnItemClickListener -import com.lukouguoji.module_base.ktx.commonAdapter -import com.lukouguoji.module_base.router.ARouterConstants -import com.lukouguoji.module_base.util.DeviceUtil -import java.util.ArrayList - -/** - * 国际出港-出港运抵页面 - * - * 布局 id 不区分设备,平板/手机由资源限定符自动选择: - * layout-sw600dp/activity_int_exp_arrive.xml(平板) - * layout/activity_int_exp_arrive.xml(手机) - */ -@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE) -class IntExpArriveActivity : - BaseBindingActivity() { - - @JvmField - @Autowired - var wbNoParam: String? = null - - override fun layoutId() = R.layout.activity_int_exp_arrive - override fun viewModelClass() = IntExpArriveViewModel::class.java - - /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ - val filterPanelVisible = ObservableBoolean(false) - - /** 供 [com.lukouguoji.gjc.holder.IntExpArriveViewHolder] 绑定 item 布局的 viewModel 变量(父类 viewModel 为 protected) */ - val itemViewModel: IntExpArriveViewModel get() = viewModel - - override fun initOnCreate(savedInstanceState: Bundle?) { - // 注入 ARouter 参数 - ARouter.getInstance().inject(this) - - setBackArrow("国际出港运抵") - binding.viewModel = viewModel - binding.activity = this - - // 手机版专属数据:加载「代理」筛选下拉 - // 平板端不调用,查询链路与请求次数与改造前完全一致 - if (DeviceUtil.isPhone()) { - viewModel.initPhoneExtras() - } - - // 如果有传入运单号,自动填充并触发搜索 - if (!wbNoParam.isNullOrEmpty()) { - viewModel.waybillNo.value = wbNoParam - viewModel.searchClick() - } - - // 绑定分页 - viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this) - - // 设置item点击监听 - binding.rv.addOnItemClickListener(viewModel) - - // 监听刷新事件 - FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { viewModel.onItemCheckChanged() } - - FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) { - viewModel.refresh() - } - - // 初始加载数据(如果没有传入运单号,才执行初始加载) - if (wbNoParam.isNullOrEmpty()) { - viewModel.refresh() - } - } - - // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 字段与数据) ==================== - - /** - * 手机版 Tab 切换回调:PhoneStatusTab 已通过双向绑定写入 viewModel.currentTab, - * 这里触发 ViewModel 把适配器数据集替换为过滤后的子集(不发起新请求)。 - */ - fun onArriveTabChanged() { - viewModel.onTabChangedPhone() - } - - /** 卡片长按:展开操作浮层(View.OnLongClickListener 要求返回 Boolean) */ - fun showCardActionPhone(bean: GjcMaWb): Boolean { - bean.actionMenuVisible.set(true) - return true - } - - /** 点击浮层遮罩/空白处:收起操作浮层 */ - fun hideCardActionPhone(bean: GjcMaWb) { - bean.actionMenuVisible.set(false) - } - - /** 选择圈勾选状态变化后回调(由 ViewHolder 调用) */ - fun onItemCheckChanged() { - viewModel.onItemCheckChanged() - } - - /** 手机版筛选弹层显隐切换 */ - fun toggleFilterPanel() { - filterPanelVisible.set(!filterPanelVisible.get()) - } - - /** 手机版筛选:重置 */ - fun resetFilter() { - viewModel.flightDate.value = "" - viewModel.flightNo.value = "" - viewModel.agentCodePhone.value = "" - } - - /** 手机版筛选:确认 */ - fun confirmFilter() { - filterPanelVisible.set(false) - viewModel.searchClick() - } - - /** - * 进入「分单明细」页:直接传递该运单已加载的 haWbList,零新增请求。 - */ - fun openSubOrder(bean: GjcMaWb) { - val list = ArrayList(bean.haWbList.orEmpty()) - IntExpArriveSubOrderActivity.start(this, bean.wbNo.orEmpty(), list) - } - - /** - * 进入「回执」页(手机专属只读页):复用 haWbList[].response + arrivalOpDate,零新增请求。 - */ - fun openReceipt(bean: GjcMaWb) { - bean.actionMenuVisible.set(false) - val list = ArrayList(bean.haWbList.orEmpty()) - IntExpArriveReceiptActivity.start(this, bean.wbNo.orEmpty(), list) - } - - /** - * 进入「补充信息」页(手机专属新页):对该运单整个 haWbList 批量应用(参照 Pad 端国际进港 - * IntArrSupplementInfoViewModel 的批量复制模式)。后端暂无保存接口,见接口问题清单。 - */ - fun openSupplement(bean: GjcMaWb) { - bean.actionMenuVisible.set(false) - val list = ArrayList(bean.haWbList.orEmpty()) - IntExpArriveSupplementActivity.start(this, bean.wbNo.orEmpty(), list) - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - when (requestCode) { - Constant.RequestCode.WAYBILL -> { - if (resultCode == Activity.RESULT_OK) { - viewModel.waybillNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT) - viewModel.searchClick() - } - } - Constant.RequestCode.CODE -> { - if (resultCode == Activity.RESULT_OK) { - viewModel.hno.value = data?.getStringExtra(Constant.Result.CODED_CONTENT) - viewModel.searchClick() - } - } - } - } -} +package com.lukouguoji.gjc.activity + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import androidx.databinding.ObservableBoolean +import com.alibaba.android.arouter.facade.annotation.Autowired +import com.alibaba.android.arouter.facade.annotation.Route +import com.alibaba.android.arouter.launcher.ARouter +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityIntExpArriveBinding +import com.lukouguoji.gjc.viewModel.IntExpArriveViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.GjcHaWb +import com.lukouguoji.module_base.bean.GjcMaWb +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.common.ConstantEvent +import com.lukouguoji.module_base.impl.FlowBus +import com.lukouguoji.module_base.impl.observe +import com.lukouguoji.module_base.ktx.addOnItemClickListener +import com.lukouguoji.module_base.ktx.commonAdapter +import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil +import java.util.ArrayList + +/** + * 国际出港-出港运抵页面 + * + * 布局 id 不区分设备,平板/手机由资源限定符自动选择: + * layout-sw600dp/activity_int_exp_arrive.xml(平板) + * layout/activity_int_exp_arrive.xml(手机) + */ +@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE) +class IntExpArriveActivity : + BaseBindingActivity() { + + @JvmField + @Autowired + var wbNoParam: String? = null + + override fun layoutId() = R.layout.activity_int_exp_arrive + override fun viewModelClass() = IntExpArriveViewModel::class.java + + /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ + val filterPanelVisible = ObservableBoolean(false) + + /** 供 [com.lukouguoji.gjc.holder.IntExpArriveViewHolder] 绑定 item 布局的 viewModel 变量(父类 viewModel 为 protected) */ + val itemViewModel: IntExpArriveViewModel get() = viewModel + + override fun initOnCreate(savedInstanceState: Bundle?) { + // 注入 ARouter 参数 + ARouter.getInstance().inject(this) + + setBackArrow(if (DeviceUtil.isPhone()) "出港运抵" else "国际出港运抵") + binding.viewModel = viewModel + binding.activity = this + + // 手机版专属数据:加载「代理」筛选下拉 + // 平板端不调用,查询链路与请求次数与改造前完全一致 + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } + + // 如果有传入运单号,自动填充并触发搜索 + if (!wbNoParam.isNullOrEmpty()) { + viewModel.waybillNo.value = wbNoParam + viewModel.searchClick() + } + + // 绑定分页 + viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this) + + // 设置item点击监听 + binding.rv.addOnItemClickListener(viewModel) + + // 监听刷新事件 + FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { viewModel.onItemCheckChanged() } + + FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) { + viewModel.refresh() + } + + // 初始加载数据(如果没有传入运单号,才执行初始加载) + if (wbNoParam.isNullOrEmpty()) { + viewModel.refresh() + } + } + + // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 字段与数据) ==================== + + /** + * 手机版 Tab 切换回调:PhoneStatusTab 已通过双向绑定写入 viewModel.currentTab, + * 这里触发 ViewModel 把适配器数据集替换为过滤后的子集(不发起新请求)。 + */ + fun onArriveTabChanged() { + viewModel.onTabChangedPhone() + } + + /** 卡片长按:展开操作浮层(View.OnLongClickListener 要求返回 Boolean) */ + fun showCardActionPhone(bean: GjcMaWb): Boolean { + bean.actionMenuVisible.set(true) + return true + } + + /** 点击浮层遮罩/空白处:收起操作浮层 */ + fun hideCardActionPhone(bean: GjcMaWb) { + bean.actionMenuVisible.set(false) + } + + /** 选择圈勾选状态变化后回调(由 ViewHolder 调用) */ + fun onItemCheckChanged() { + viewModel.onItemCheckChanged() + } + + /** 手机版筛选弹层显隐切换 */ + fun toggleFilterPanel() { + filterPanelVisible.set(!filterPanelVisible.get()) + } + + /** 手机版筛选:重置 */ + fun resetFilter() { + viewModel.flightDate.value = "" + viewModel.flightNo.value = "" + viewModel.agentCodePhone.value = "" + } + + /** 手机版筛选:确认 */ + fun confirmFilter() { + filterPanelVisible.set(false) + viewModel.searchClick() + } + + /** + * 进入「分单明细」页:直接传递该运单已加载的 haWbList,零新增请求。 + */ + fun openSubOrder(bean: GjcMaWb) { + val list = ArrayList(bean.haWbList.orEmpty()) + IntExpArriveSubOrderActivity.start(this, bean.wbNo.orEmpty(), list) + } + + /** + * 进入「回执」页(手机专属只读页):复用 haWbList[].response + arrivalOpDate,零新增请求。 + */ + fun openReceipt(bean: GjcMaWb) { + bean.actionMenuVisible.set(false) + val list = ArrayList(bean.haWbList.orEmpty()) + IntExpArriveReceiptActivity.start(this, bean.wbNo.orEmpty(), list) + } + + /** + * 进入「补充信息」页(手机专属新页):对该运单整个 haWbList 批量应用(参照 Pad 端国际进港 + * IntArrSupplementInfoViewModel 的批量复制模式)。后端暂无保存接口,见接口问题清单。 + */ + fun openSupplement(bean: GjcMaWb) { + bean.actionMenuVisible.set(false) + val list = ArrayList(bean.haWbList.orEmpty()) + IntExpArriveSupplementActivity.start(this, bean.wbNo.orEmpty(), list) + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + when (requestCode) { + Constant.RequestCode.WAYBILL -> { + if (resultCode == Activity.RESULT_OK) { + viewModel.waybillNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT) + viewModel.searchClick() + } + } + Constant.RequestCode.CODE -> { + if (resultCode == Activity.RESULT_OK) { + viewModel.hno.value = data?.getStringExtra(Constant.Result.CODED_CONTENT) + viewModel.searchClick() + } + } + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverActivity.kt index 25e1f83..243ff95 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverActivity.kt @@ -35,7 +35,7 @@ class IntExpOutHandoverActivity : val filterPanelVisible = ObservableBoolean(false) override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("国际出港出库交接") + setBackArrow(if (DeviceUtil.isPhone()) "出库交接" else "国际出港出库交接") binding.viewModel = viewModel binding.activity = this diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt index 26dc0a1..e78fcff 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveActivity.kt @@ -1,171 +1,171 @@ -package com.lukouguoji.gjc.page.move - -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.os.Bundle -import androidx.databinding.ObservableBoolean -import com.alibaba.android.arouter.facade.annotation.Route -import com.lukouguoji.gjc.R -import com.lukouguoji.gjc.databinding.ActivityIntExpMoveBinding -import com.lukouguoji.gjc.viewModel.IntExpMoveViewModel -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.common.Constant -import com.lukouguoji.module_base.common.ConstantEvent -import com.lukouguoji.module_base.impl.FlowBus -import com.lukouguoji.module_base.impl.observe -import com.lukouguoji.module_base.ktx.addOnItemClickListener -import com.lukouguoji.module_base.ktx.showToast -import com.lukouguoji.module_base.model.ConfirmDialogModel -import com.lukouguoji.module_base.model.ScanModel -import com.lukouguoji.module_base.router.ARouterConstants -import com.lukouguoji.module_base.util.DeviceUtil - -/** - * 国际出港-出港移库 - */ -@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_MOVE) -class IntExpMoveActivity : BaseBindingActivity() { - - // 布局 id 不区分设备,平板/手机由资源限定符自动选择: - // layout-sw600dp/activity_int_exp_move.xml(平板) / layout/activity_int_exp_move.xml(手机) - override fun layoutId() = R.layout.activity_int_exp_move - - override fun viewModelClass() = IntExpMoveViewModel::class.java - - /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ - val filterPanelVisible = ObservableBoolean(false) - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("国际出港移库") - binding.viewModel = viewModel - binding.activity = this - - // 手机版专属数据:默认「待移库」Tab、Tab 角标计数、特码下拉 - // 平板端不调用,查询链路与请求次数与改造前完全一致 - if (DeviceUtil.isPhone()) { - viewModel.initPhoneExtras() - } - - initRecyclerView() - initListeners() - observeData() - } - - /** - * 初始化RecyclerView - */ - private fun initRecyclerView() { - viewModel.pageModel.bindSmartRefreshLayout( - binding.srl, - binding.rv, - viewModel, - this - ) - binding.rv.addOnItemClickListener(viewModel) - } - - /** - * 初始化监听器 - */ - private fun initListeners() { - // 移库按钮:btnMove 只存在于平板变体(手机版底部条走 setOnActionClick),故判空 - binding.btnMove?.setOnClickListener { - showMoveConfirmDialog() - } - } - - /** - * 观察数据变化 - */ - private fun observeData() { - // 监听item选择变化事件,更新全选状态 - FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { - viewModel.onItemCheckChanged() - } - - // 监听刷新事件 - FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) { - viewModel.refresh() - } - - // 初始加载数据 - viewModel.refresh() - } - - /** - * 扫码运单号 - */ - fun scanWaybill() { - ScanModel.startScan(this, Constant.RequestCode.WAYBILL) - } - - // ==================== 手机版专用交互(复用既有 ViewModel 字段,无新增业务逻辑) ==================== - - /** - * 手机版筛选弹层显隐切换 - */ - fun toggleFilterPanel() { - filterPanelVisible.set(!filterPanelVisible.get()) - } - - /** - * 手机版筛选:重置 - * - * 只清空弹层内的三个条件(承运人 / 运单类型 / 特码),不影响 Tab 与顶部搜索框。 - */ - fun resetFilter() { - viewModel.by1.value = "" - viewModel.awbType.value = "" - viewModel.spCode.value = "" - } - - /** - * 手机版筛选:确定 - */ - fun confirmFilter() { - filterPanelVisible.set(false) - viewModel.searchClick() - } - - /** - * 显示移库确认对话框 - * - * 手机版底部操作条通过 XML 的 setOnActionClick 调用,故为 public。 - */ - fun showMoveConfirmDialog() { - val selectedItems = viewModel.getSelectedItems() - - if (selectedItems.isEmpty()) { - showToast("请至少选择一条运单") - return - } - - ConfirmDialogModel( - message = "确定要移库选中的 ${selectedItems.size} 条运单吗?", - title = "移库确认" - ) { - viewModel.submitMove() - }.show() - } - - /** - * 扫码回调 - */ - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - if (requestCode == Constant.RequestCode.WAYBILL && resultCode == Activity.RESULT_OK) { - val code = data?.getStringExtra(Constant.Result.CODED_CONTENT) - viewModel.waybillNo.value = code - viewModel.searchClick() - } - } - - companion object { - @JvmStatic - fun start(context: Context) { - val starter = Intent(context, IntExpMoveActivity::class.java) - context.startActivity(starter) - } - } -} +package com.lukouguoji.gjc.page.move + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.databinding.ObservableBoolean +import com.alibaba.android.arouter.facade.annotation.Route +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityIntExpMoveBinding +import com.lukouguoji.gjc.viewModel.IntExpMoveViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.common.ConstantEvent +import com.lukouguoji.module_base.impl.FlowBus +import com.lukouguoji.module_base.impl.observe +import com.lukouguoji.module_base.ktx.addOnItemClickListener +import com.lukouguoji.module_base.ktx.showToast +import com.lukouguoji.module_base.model.ConfirmDialogModel +import com.lukouguoji.module_base.model.ScanModel +import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil + +/** + * 国际出港-出港移库 + */ +@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_MOVE) +class IntExpMoveActivity : BaseBindingActivity() { + + // 布局 id 不区分设备,平板/手机由资源限定符自动选择: + // layout-sw600dp/activity_int_exp_move.xml(平板) / layout/activity_int_exp_move.xml(手机) + override fun layoutId() = R.layout.activity_int_exp_move + + override fun viewModelClass() = IntExpMoveViewModel::class.java + + /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ + val filterPanelVisible = ObservableBoolean(false) + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow(if (DeviceUtil.isPhone()) "出港移库" else "国际出港移库") + binding.viewModel = viewModel + binding.activity = this + + // 手机版专属数据:默认「待移库」Tab、Tab 角标计数、特码下拉 + // 平板端不调用,查询链路与请求次数与改造前完全一致 + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } + + initRecyclerView() + initListeners() + observeData() + } + + /** + * 初始化RecyclerView + */ + private fun initRecyclerView() { + viewModel.pageModel.bindSmartRefreshLayout( + binding.srl, + binding.rv, + viewModel, + this + ) + binding.rv.addOnItemClickListener(viewModel) + } + + /** + * 初始化监听器 + */ + private fun initListeners() { + // 移库按钮:btnMove 只存在于平板变体(手机版底部条走 setOnActionClick),故判空 + binding.btnMove?.setOnClickListener { + showMoveConfirmDialog() + } + } + + /** + * 观察数据变化 + */ + private fun observeData() { + // 监听item选择变化事件,更新全选状态 + FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { + viewModel.onItemCheckChanged() + } + + // 监听刷新事件 + FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) { + viewModel.refresh() + } + + // 初始加载数据 + viewModel.refresh() + } + + /** + * 扫码运单号 + */ + fun scanWaybill() { + ScanModel.startScan(this, Constant.RequestCode.WAYBILL) + } + + // ==================== 手机版专用交互(复用既有 ViewModel 字段,无新增业务逻辑) ==================== + + /** + * 手机版筛选弹层显隐切换 + */ + fun toggleFilterPanel() { + filterPanelVisible.set(!filterPanelVisible.get()) + } + + /** + * 手机版筛选:重置 + * + * 只清空弹层内的三个条件(承运人 / 运单类型 / 特码),不影响 Tab 与顶部搜索框。 + */ + fun resetFilter() { + viewModel.by1.value = "" + viewModel.awbType.value = "" + viewModel.spCode.value = "" + } + + /** + * 手机版筛选:确定 + */ + fun confirmFilter() { + filterPanelVisible.set(false) + viewModel.searchClick() + } + + /** + * 显示移库确认对话框 + * + * 手机版底部操作条通过 XML 的 setOnActionClick 调用,故为 public。 + */ + fun showMoveConfirmDialog() { + val selectedItems = viewModel.getSelectedItems() + + if (selectedItems.isEmpty()) { + showToast("请至少选择一条运单") + return + } + + ConfirmDialogModel( + message = "确定要移库选中的 ${selectedItems.size} 条运单吗?", + title = "移库确认" + ) { + viewModel.submitMove() + }.show() + } + + /** + * 扫码回调 + */ + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == Constant.RequestCode.WAYBILL && resultCode == Activity.RESULT_OK) { + val code = data?.getStringExtra(Constant.Result.CODED_CONTENT) + viewModel.waybillNo.value = code + viewModel.searchClick() + } + } + + companion object { + @JvmStatic + fun start(context: Context) { + val starter = Intent(context, IntExpMoveActivity::class.java) + context.startActivity(starter) + } + } +} diff --git a/module_gjc/src/main/res/layout/item_gjc_weighing.xml b/module_gjc/src/main/res/layout/item_gjc_weighing.xml index 12b55aa..643b6dd 100644 --- a/module_gjc/src/main/res/layout/item_gjc_weighing.xml +++ b/module_gjc/src/main/res/layout/item_gjc_weighing.xml @@ -75,23 +75,51 @@ android:layout_marginTop="12dp" android:orientation="horizontal"> - + android:gravity="center_vertical" + android:orientation="horizontal"> - + + + + + + + android:gravity="center_vertical" + android:orientation="horizontal"> + + + + + + @@ -102,23 +130,54 @@ android:layout_marginTop="8dp" android:orientation="horizontal"> - + android:gravity="center_vertical" + android:orientation="horizontal"> - + + + + + + + android:gravity="center_vertical" + android:orientation="horizontal"> + + + + + + diff --git a/module_gjc/src/main/res/layout/item_gjc_weighing_record.xml b/module_gjc/src/main/res/layout/item_gjc_weighing_record.xml index 8f23284..07fe776 100644 --- a/module_gjc/src/main/res/layout/item_gjc_weighing_record.xml +++ b/module_gjc/src/main/res/layout/item_gjc_weighing_record.xml @@ -56,14 +56,28 @@ - + android:gravity="center_vertical" + android:orientation="horizontal"> + + + + + + Date: Mon, 3 Aug 2026 12:17:10 +0800 Subject: [PATCH 12/29] =?UTF-8?q?fix:=20=E8=BF=9B=E6=B8=AF=E7=A7=BB?= =?UTF-8?q?=E5=BA=93=E5=BD=92=E5=B1=9E=E6=9B=B4=E6=AD=A3=E2=80=94=E2=80=94?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E8=AF=AF=E5=BB=BAIntImpMove=EF=BC=8C?= =?UTF-8?q?=E9=87=8D=E6=96=B0=E9=80=82=E9=85=8D=E5=88=B0=E5=9B=BD=E5=86=85?= =?UTF-8?q?=E8=BF=9B=E6=B8=AFDomImpMove?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 设计稿11「进港移库」经确认归属国内进港移库(DomImpMove后端8接口齐全), 此前误判为国际进港并预接了不存在的IntImpMove模块(问题清单#31作废)。 - 删除module_gjj的IntImpMove全套实现(3页面+Bean+Api+菜单+路由+权限串) - GnjMoveStashListActivity双形态适配:待移库/已移库Tab走search/searchMoved 双端点,Tab角标、筛选弹层4项、全选/批量移库复用平板既有链路 - 新增手机专属页:运单详情(Intent传bean零请求)+拍照上传(detail回填 已有照片,modify最小体三字段提交,与平板移交编辑页同链路) - 手机首页入口改挂国内Tab(GnViewModel补通用route跳转,权限串AppDomImpMove) - 内网真实数据双端验证通过;Proxyman A/B:wbNo/awbType生效, fdate/fno/spCode被后端静默忽略(#32)、opId/opDate恒null(#33) - 问题清单更正#31+新增#32~#34,CLAUDE.md/CHANGELOG/api-doc.md同步 Co-Authored-By: Claude Fable 5 --- .../skills/phone-adapt/references/api-doc.md | 20 +- CHANGELOG.md | 22 + CLAUDE.md | 27 +- app/src/debug/AndroidManifest.xml | 16 +- app/src/main/AndroidManifest.xml | 35 +- .../detail/GnjMoveStashDetailActivity.kt | 49 ++ .../detail/GnjMoveStashDetailViewModel.kt | 25 + .../stash/list/GnjMoveStashListActivity.kt | 140 ++++-- .../stash/list/GnjMoveStashListViewHolder.kt | 36 +- .../stash/list/GnjMoveStashListViewModel.kt | 101 +++- .../stash/photo/GnjMoveStashPhotoActivity.kt | 45 ++ .../stash/photo/GnjMoveStashPhotoViewModel.kt | 84 ++-- .../activity_gnj_move_stash_list.xml | 153 +++++++ .../item_gnj_move_stash_list.xml | 296 ++++++++++++ .../layout/activity_gnj_move_stash_detail.xml | 30 +- .../layout/activity_gnj_move_stash_list.xml | 314 +++++++------ .../layout/activity_gnj_move_stash_photo.xml | 8 +- .../res/layout/item_gnj_move_stash_list.xml | 430 ++++++++---------- documents/后端接口对接问题清单.xlsx | Bin 23556 -> 24648 bytes .../module_base/bean/IntImpMoveBean.kt | 78 ---- .../module_base/bean/MoveStashBean.kt | 16 + .../lukouguoji/module_base/common/Constant.kt | 1 - .../lukouguoji/module_base/http/net/Api.kt | 39 +- .../module_base/router/ARouterConstants.kt | 2 +- .../gjj/activity/IntImpMoveActivity.kt | 147 ------ .../gjj/activity/IntImpMoveDetailActivity.kt | 46 -- .../gjj/activity/IntImpMovePhotoActivity.kt | 45 -- .../gjj/holder/IntImpMoveViewHolder.kt | 48 -- .../viewModel/IntImpMoveDetailViewModel.kt | 26 -- .../gjj/viewModel/IntImpMoveViewModel.kt | 187 -------- .../main/res/layout/activity_int_imp_move.xml | 166 ------- .../src/main/res/layout/item_int_imp_move.xml | 230 ---------- .../sixin/module_p/ui/enter/gj/GjViewModel.kt | 8 - .../sixin/module_p/ui/enter/gn/GnViewModel.kt | 16 + .../res/drawable-xxhdpi/gnj_yi_ku_icon.png | Bin 0 -> 26578 bytes 35 files changed, 1341 insertions(+), 1545 deletions(-) create mode 100644 app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/detail/GnjMoveStashDetailActivity.kt create mode 100644 app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/detail/GnjMoveStashDetailViewModel.kt create mode 100644 app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoActivity.kt rename module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMovePhotoViewModel.kt => app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoViewModel.kt (61%) create mode 100644 app/src/main/res/layout-sw600dp/activity_gnj_move_stash_list.xml create mode 100644 app/src/main/res/layout-sw600dp/item_gnj_move_stash_list.xml rename module_gjj/src/main/res/layout/activity_int_imp_move_detail.xml => app/src/main/res/layout/activity_gnj_move_stash_detail.xml (93%) rename module_gjj/src/main/res/layout/activity_int_imp_move_photo.xml => app/src/main/res/layout/activity_gnj_move_stash_photo.xml (93%) delete mode 100644 module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpMoveBean.kt delete mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveActivity.kt delete mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveDetailActivity.kt delete mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMovePhotoActivity.kt delete mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpMoveViewHolder.kt delete mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveDetailViewModel.kt delete mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveViewModel.kt delete mode 100644 module_gjj/src/main/res/layout/activity_int_imp_move.xml delete mode 100644 module_gjj/src/main/res/layout/item_int_imp_move.xml create mode 100644 module_p/src/main/res/drawable-xxhdpi/gnj_yi_ku_icon.png diff --git a/.claude/skills/phone-adapt/references/api-doc.md b/.claude/skills/phone-adapt/references/api-doc.md index eb54f1b..2354a46 100644 --- a/.claude/skills/phone-adapt/references/api-doc.md +++ b/.claude/skills/phone-adapt/references/api-doc.md @@ -115,10 +115,22 @@ curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \ `outState`(0 未出库/1 已出库)文档为 integer,前端传字符串靠 Jackson 隐式转换;`pageQueryTotal` 出参无已入库/已出库分项计数(缺口 #30,手机三格统计为客户端计数口径:dlvTime 非空=已出库、 inDate 非空=已入库);出参含 `agentName`(中文名)+ `agentCode`,agentName 可为 null -- `IntImpMove`(进港移库,2026-07-31 文档核对):**后端整个模块不存在**(api-doc 仅有国内进港 - `DomImpMove` 与国际出港 `IntExpMove`),权限串也没有对应 key(缺口 #31)。前端按 IntExpMove - 同名约定预接 `pageQuery`/`pageQueryTotal`/`move`/`uploadPic` 四接口 + 预定义权限串 - `AppIntImpMove`,后端交付后前端零改动生效 +- 「进港移库」(设计稿 11)**归属更正(2026-08-03 用户确认):属国内进港移库 `DomImpMove`**, + 不是国际进港移库——「后端模块缺失」的旧结论(原缺口 #31)作废,原按 IntExpMove 约定预接的 + IntImpMove 前端实现已整体删除。溯源:api-doc 53 模块中移库仅 `DomImpMove`(国内进港,8 接口)与 + `IntExpMove`(国际出港,4 接口),移库按转关业务前缀划分(DomImpMove 处理 `CI**`、IntExpMove + 处理 `IO**`),设计稿详情卡的「国际进港」红标签实为 `awbType` 值(如「国际进港(国内中转)」), + 不代表页面归属 +- `DomImpMove`(国内进港移库,2026-08-03 内网实测):手机 Tab 双端点——待移库 `search` / + 已移库 `searchMoved`(同一套入参 schema,分页参数名 **`page`/`limit`**);入参 A/B 实测: + **`wbNo`、`awbType`(值为 CICO/CIII/CIIO 转关码)过滤生效;`fdate`/`fno`/`spCode` 文档有定义但 + 被静默忽略**(缺口 #32);`searchMoved`/`detail` 出参 **`opId`/`opDate` 恒 null** 且无操作人姓名 + 字段(缺口 #33,移库人/移库时间显示"-"),`moveId` 形如 `CICO240617155016` 疑似内嵌移库时间戳但无 + 文档语义;`searchMoved` 出参**无 pic 三字段**(search 有)——拍照上传页统一先调 `GET detail` + 回填已有照片(#34 前端已规避);照片提交走 `modify` 最小体 + `{mawbId, remark, picNumber, pic, originalPic}`(平板移交编辑页同链路,removeEmptyOrNull); + 批量移库 `move` 入参 `{fid:"0", ids:[mawbId]}`;国内进港特码字典 + `DictUtils.getSpecialCodeList(flag=0, ieFlag="I")` 实测取数正常 - `IntExpCheckIn`(出港计重,2026-07-29 内网实测):`likeNo` **并非任意模糊**——按 8 位 `no` 匹配(11 位 wbNo 或部分号均 0 条),11 位全号必须走 `wbNo`;`checkIn`/`checkInList` 文档有定义但 `pageQuery`/`pageQueryTotal` **均静默忽略**(缺口 #12,待计重/计重中计数依赖); diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ea617b..8777990 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,28 @@ ## [Unreleased] +### 变更 (Changed) +- 【进港移库归属更正 · 2026-08-03】设计稿 11「进港移库」经确认归属**国内进港移库 + (DomImpMove,后端 8 接口齐全,Pad 首页「国内进港→进港移库」既有页面)**,此前误判为 + 国际进港并按 IntExpMove 约定预接不存在的 IntImpMove 模块(原问题清单 #31 作废)。处置: + ① 删除 module_gjj 的 IntImpMove 全套前端实现(3 Activity + 3 ViewModel + Holder + 4 布局 + + `IntImpMoveBean` + Api 4 方法 + 国际 Tab 菜单项 + 权限串/路由/双 Manifest 注册); + ② 按 phone-adapt 流程重新适配到 `GnjMoveStashListActivity`(app 模块):主列表双形态 + (Pad 布局移 layout-sw600dp 零改动;手机版 = PhoneSearchBar + 待移库/已移库 Tab + (`DomImpMove/search`/`searchMoved` 双端点,`searchMoved` 无移库标识按端点打 `isMoved`)+ + 角标(双端点 limit=1 取 total,仅手机发起)+ 筛选弹层 4 项 + 全选/已选计数 + 批量移库 + (复用平板 `move` 链路)+ 卡片长按「拍照」浮层);新增手机专属页 + `GnjMoveStashDetailActivity`(Intent 传 bean 零请求,三卡片)与 + `GnjMoveStashPhotoActivity`(先调 `detail` 回填已有照片,提交走 `modify` 最小体 + 三字段规范,与平板移交编辑页同链路);`MoveStashBean` 增 `agentName`/`isMoved`/ + `actionMenuVisible`/`agentDisplay`/`orDash`;手机首页入口改挂**国内 Tab**(`GnViewModel` + 补通用 route 跳转,权限串 `GnjYiKu=AppDomImpMove` 与 Pad 一致,新路由 + `/app/GnjMoveStashListActivity`)。 + 2026-08-03 内网真实数据双端验证通过(登录→国内 Tab→列表/Tab/详情/筛选/全选/长按拍照全链路 + crash=0;平板回归原行为零变化);Proxyman A/B:`wbNo`/`awbType` 过滤生效, + `fdate`/`fno`/`spCode` 被后端静默忽略(新缺口 #32)、`searchMoved`/`detail` 出参 + `opId`/`opDate` 恒 null 且无姓名字段(#33)、`searchMoved` 无 pic 三字段(#34,前端已规避) + ### 新增 (Added) - 「进港查询」5.5 寸手机端适配(设计稿 10_进港查询,06 出港查询的进港镜像;详情页与运单追踪 复用 08/06 已适配页零新增):列表 `IntImpQueryActivity`(module_gjj,首页菜单实际跳转页; diff --git a/CLAUDE.md b/CLAUDE.md index fdefd92..c8fec9f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1150,15 +1150,21 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = `goods`);详情页与运单追踪复用 08/06 已适配页零新增;平板侧滑筛选面板代码已判空守卫。 ⚠️ 踩坑:代理人绑定不能写 `bean.agentName ?? bean.agentCode`——转换器把 JSON null 归一成 空串,`??` 只判 null 不判空串,须用 Bean 计算属性 `agentDisplay`(06 出港查询同步修正)) - - 「进港移库」`IntImpMoveActivity` + `IntImpMoveDetailActivity` + `IntImpMovePhotoActivity` - (module_gjj,**首个后端整模块缺失的设计稿页**:api-doc 确认无 IntImpMove 模块、权限串无 - 对应 key(缺口 #31)。前端按设计稿完整实现、按 IntExpMove 同名约定预接 - pageQuery/pageQueryTotal/move/uploadPic + 预定义权限串 `AppIntImpMove`,后端交付后零改动 - 生效;权限串下发前手机首页无入口,debug 直启验证。结构镜像 05 出港移库(Tab/批量移库/筛选 - 4 项),新增交互:卡片长按浮层「拍照」(复用 04 运抵的 actionMenuVisible 模式)→ 拍照上传页 - (图片网格复用 module_base `ImageSelectNewViewHolder`,提交走 pic/originalPic/picNumber - 三字段规范);详情页三卡片:基本信息/移库信息(仅已移库)/异常照片。手机专属新页无平板变体, - 布局只放 `res/layout/`;UI 与交互已用 Proxyman Map Local mock 全量验证) + - 「进港移库」`GnjMoveStashListActivity`(app 模块,**2026-08-03 归属更正后重做**:设计稿 11 + 实际归属**国内进港移库 DomImpMove**(后端 8 接口齐全、Pad 首页「国内进港→进港移库」既有页面), + 最初误判为国际进港并按 IntExpMove 约定预接了不存在的 IntImpMove 模块(原缺口 #31),该套 + module_gjj 前端实现已整体删除。现行实现:主列表双形态(Pad 布局移 layout-sw600dp 零改动), + 待移库/已移库 Tab 走 **`search`/`searchMoved` 双端点**(`searchMoved` 出参无移库标识,前端按 + 端点给 bean 打 `isMoved`),Tab 角标 = 两端点各调一次 limit=1 取分页 total(`initPhoneExtras` + 开关,仅手机发起);手机专属新页 `GnjMoveStashDetailActivity`(Intent 传 bean 零请求,三卡片: + 基本信息/移库信息(仅已移库)/异常照片)+ `GnjMoveStashPhotoActivity`(进入先调 `detail` 回填 + 已有照片——`searchMoved` 出参无 pic 三字段 #34,提交走 **`modify` 最小体** + `{mawbId,remark,picNumber,pic,originalPic}`,与平板移交编辑页同链路);批量移库复用平板 + `moveStashClick`(`move`:fid+ids)。手机首页入口在**国内 Tab**(`GnViewModel`,权限串 + `GnjYiKu=AppDomImpMove`,需补通用 route 跳转逻辑,图标从 module_gnj 复制); + GnjMoveStashListActivity 补 @Route `/app/GnjMoveStashListActivity`。 + 2026-08-03 内网真实数据双端验证通过;筛选 A/B:`wbNo`/`awbType` 生效, + `fdate`/`fno`/`spCode` 被后端静默忽略(#32)、`opId`/`opDate` 恒 null(#33)) - 「进港仓库」`IntImpStorageUseActivity`(module_gjj,07 出港仓库的进港镜像;**首页菜单实际跳转页, 旧版 `GjjWareHouseActivity` 路由已注释弃用**。差异:卡片/筛选用始发站(fdep 入参)替代目的站; 搜索框「运单号/航班号」分流(含字母→fno、其余→wbNo,抓包证实);筛选 5 项无入参(缺口 #25, @@ -1186,7 +1192,8 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = - ✅ **设计稿 11 个入口(01~11)已于 2026-07-31 全部适配完成** - ⏳ **待办**: - `PhoneSearchBar` 接入 AutoQuery 联想(`AutoQueryManager` 目前只对接了 Pad 系组件) - - 进港移库待后端交付 IntImpMove 模块(四接口 + 权限串 AppIntImpMove,缺口 #31)后联调 + - 进港移库筛选三项(航班日期/航班号/特码)待后端实装 `fdate`/`fno`/`spCode` 入参(缺口 #32)、 + 移库人/移库时间待后端回填 `opId`/`opDate` 并补姓名出参(缺口 #33)后自动生效 - 出库交接 Tab 角标恒 0:`IntExpOutHandover/pageQueryTotal` 出参恒 0(后端缺陷,问题清单 #6), 后端修复后角标自动恢复(`handoverState` 过滤本身已于 2026-07-29 实机验证通过)生效 - 📋 **接口对接**:适配中发现的后端接口缺口统一记录在 `documents/后端接口对接问题清单.xlsx` diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml index 8717d8c..cfe6128 100644 --- a/app/src/debug/AndroidManifest.xml +++ b/app/src/debug/AndroidManifest.xml @@ -158,9 +158,21 @@ android:exported="true" tools:replace="android:exported" /> - + + + + + + + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2a9b492..c4bb10a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -375,6 +375,20 @@ android:name=".page.gnj.move.stash.list.GnjMoveStashListActivity" android:configChanges="orientation|keyboardHidden" android:screenOrientation="unspecified" /> + + + + + + - - - - - - - - - () { + + override fun layoutId() = R.layout.activity_gnj_move_stash_detail + override fun viewModelClass() = GnjMoveStashDetailViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("运单详情") + binding.viewModel = viewModel + binding.activity = this + viewModel.initOnCreated(intent) + } + + /** 「异常照片」加号槽位 → 拍照上传页 */ + fun openPhoto() { + viewModel.dataBean.value?.let { + GnjMoveStashPhotoActivity.start(this, it.mawbId, it.wbNo) + } + } + + companion object { + @JvmStatic + fun start(context: Context, bean: MoveStashBean) { + context.startActivity( + Intent(context, GnjMoveStashDetailActivity::class.java) + .putExtra(Constant.Key.DATA, Gson().toJson(bean)) + ) + } + } +} diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/detail/GnjMoveStashDetailViewModel.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/detail/GnjMoveStashDetailViewModel.kt new file mode 100644 index 0000000..4cca875 --- /dev/null +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/detail/GnjMoveStashDetailViewModel.kt @@ -0,0 +1,25 @@ +package com.lukouguoji.aerologic.page.gnj.move.stash.detail + +import android.content.Intent +import androidx.lifecycle.MutableLiveData +import com.google.gson.Gson +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.MoveStashBean +import com.lukouguoji.module_base.common.Constant + +/** + * 国内进港移库「运单详情」ViewModel(5.5 寸手持端专属页面) + * + * 列表项数据已包含详情页所需全部字段(含 isMoved 端点打标),直接由列表带入,不额外请求。 + */ +class GnjMoveStashDetailViewModel : BaseViewModel() { + + val dataBean = MutableLiveData(MoveStashBean()) + + fun initOnCreated(intent: Intent) { + val json = intent.getStringExtra(Constant.Key.DATA).orEmpty() + if (json.isNotEmpty()) { + dataBean.value = Gson().fromJson(json, MoveStashBean::class.java) + } + } +} diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListActivity.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListActivity.kt index 86a24b3..3f1de6c 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListActivity.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListActivity.kt @@ -1,36 +1,104 @@ -package com.lukouguoji.aerologic.page.gnj.move.stash.list - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import com.lukouguoji.aerologic.R -import com.lukouguoji.aerologic.databinding.ActivityGnjMoveStashListBinding -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.ktx.getLifecycleOwner - -class GnjMoveStashListActivity : - BaseBindingActivity() { - override fun layoutId() = R.layout.activity_gnj_move_stash_list - - override fun viewModelClass() = GnjMoveStashListViewModel::class.java - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("国内进港移库") - - binding.viewModel = viewModel - - viewModel.pageModel - .bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner()) - - viewModel.refresh() - } - - companion object { - @JvmStatic - fun start(context: Context) { - val starter = Intent(context, GnjMoveStashListActivity::class.java) - context.startActivity(starter) - } - } - -} \ No newline at end of file +package com.lukouguoji.aerologic.page.gnj.move.stash.list + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.databinding.ObservableBoolean +import com.alibaba.android.arouter.facade.annotation.Route +import com.lukouguoji.aerologic.R +import com.lukouguoji.aerologic.databinding.ActivityGnjMoveStashListBinding +import com.lukouguoji.aerologic.page.gnj.move.stash.photo.GnjMoveStashPhotoActivity +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.MoveStashBean +import com.lukouguoji.module_base.common.ConstantEvent +import com.lukouguoji.module_base.impl.FlowBus +import com.lukouguoji.module_base.impl.observe +import com.lukouguoji.module_base.ktx.getLifecycleOwner +import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil + +@Route(path = ARouterConstants.ACTIVITY_URL_GNJ_MOVE_STASH_LIST) +class GnjMoveStashListActivity : + BaseBindingActivity() { + override fun layoutId() = R.layout.activity_gnj_move_stash_list + + override fun viewModelClass() = GnjMoveStashListViewModel::class.java + + /** 筛选弹层显隐(仅手机 UI 状态,平板布局不绑定) */ + val filterPanelVisible = ObservableBoolean(false) + + override fun initOnCreate(savedInstanceState: Bundle?) { + // 设计稿手机端标题为「进港移库」,平板保持原标题 + setBackArrow(if (DeviceUtil.isPhone()) "进港移库" else "国内进港移库") + + binding.viewModel = viewModel + binding.activity = this + + viewModel.pageModel + .bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner()) + + if (DeviceUtil.isPhone()) { + // 手机专属:Tab 角标 + 特码字典等额外请求 + viewModel.initPhoneExtras() + + // 卡片勾选变化 → 更新全选状态与已选计数 + FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { + viewModel.updateCheckAllStatus() + } + } + + // 拍照上传等子页面完成后刷新列表(平板无发射方,观察无副作用) + FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) { + viewModel.refresh() + } + + viewModel.refresh() + } + + // ==================== 筛选弹层(仅手机) ==================== + + fun toggleFilterPanel() { + filterPanelVisible.set(!filterPanelVisible.get()) + } + + /** 筛选:重置(只清空弹层内条件,不影响 Tab 与顶部搜索框) */ + fun resetFilter() { + viewModel.flightDate.value = "" + viewModel.flightNo.value = "" + viewModel.spCode.value = "" + viewModel.businessType.value = "" + } + + fun confirmFilter() { + filterPanelVisible.set(false) + viewModel.refresh() + } + + // ==================== 卡片长按「拍照」浮层(仅手机) ==================== + + /** 卡片长按:展开操作浮层(View.OnLongClickListener 要求返回 Boolean) */ + fun showCardActionPhone(bean: MoveStashBean): Boolean { + bean.actionMenuVisible.set(true) + return true + } + + /** 点浮层空白处关闭 */ + fun hideCardActionPhone(bean: MoveStashBean) { + bean.actionMenuVisible.set(false) + } + + /** 浮层「拍照」→ 拍照上传页 */ + fun openPhoto(bean: MoveStashBean) { + bean.actionMenuVisible.set(false) + GnjMoveStashPhotoActivity.start(this, bean.mawbId, bean.wbNo) + } + + companion object { + @JvmStatic + fun start(context: Context) { + val starter = Intent(context, GnjMoveStashListActivity::class.java) + context.startActivity(starter) + } + } + +} diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewHolder.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewHolder.kt index 0304c4d..f337635 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewHolder.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewHolder.kt @@ -3,34 +3,64 @@ package com.lukouguoji.aerologic.page.gnj.move.stash.list import android.view.View import android.widget.Toast import com.lukouguoji.aerologic.databinding.ItemGnjMoveStashListBinding +import com.lukouguoji.aerologic.page.gnj.move.stash.detail.GnjMoveStashDetailActivity import com.lukouguoji.gnj.page.yiku.handover.GnjYiKuHandoverActivity import com.lukouguoji.module_base.base.BaseViewHolder import com.lukouguoji.module_base.bean.MoveStashBean +import com.lukouguoji.module_base.common.ConstantEvent +import com.lukouguoji.module_base.impl.FlowBus +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +/** + * 国内进港移库列表项 ViewHolder(双形态共用) + * + * 平板/手机布局差异较大,单侧独有的控件 id 在 Binding 基类中为 @Nullable, + * 全部走判空调用(平板:swipe_menu/btn_edit/ll;手机:ll_detail)。 + */ class GnjMoveStashListViewHolder(view: View) : BaseViewHolder(view) { override fun onBind(item: Any?, position: Int) { val bean = getItemBean(item)!! binding.bean = bean + binding.position = position + binding.activity = itemView.context as? GnjMoveStashListActivity + // 勾选框(双形态共有):切换选中;手机端另行广播刷新全选/已选计数 binding.ivIcon.setOnClickListener { bean.checked.set(!bean.checked.get()) + binding.executePendingBindings() + + GlobalScope.launch { + FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).emit("check_changed") + } } + // ===== 平板独有交互 ===== + // 点击列表项进入移交详情 - binding.ll.setOnClickListener { + binding.ll?.setOnClickListener { GnjYiKuHandoverActivity.startForDetails(itemView.context, bean.mawbId) } // 侧滑菜单 - 编辑按钮 - binding.btnEdit.setOnClickListener { - binding.swipeMenu.quickClose() + binding.btnEdit?.setOnClickListener { + binding.swipeMenu?.quickClose() if (bean.pickFlag == "1") { Toast.makeText(itemView.context, "已出库,不可编辑", Toast.LENGTH_SHORT).show() return@setOnClickListener } GnjYiKuHandoverActivity.startForEdit(itemView.context, bean.mawbId) } + + // ===== 手机独有交互 ===== + + // 「查看详情」→ 手机版运单详情页 + binding.llDetail?.setOnClickListener { + GnjMoveStashDetailActivity.start(itemView.context, bean) + } + + binding.executePendingBindings() } } diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewModel.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewModel.kt index 9295d2c..a9b4b21 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewModel.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewModel.kt @@ -49,6 +49,41 @@ class GnjMoveStashListViewModel : BasePageViewModel() { val number = MutableLiveData("0") val weight = MutableLiveData("0") + // ========== 5.5 寸手持端专属字段(平板布局不绑定,默认值保证平板行为零变化) ========== + + /** 移库状态 Tab:"0" 待移库(DomImpMove/search)/ "1" 已移库(DomImpMove/searchMoved) */ + val moveState = MutableLiveData("0") + + /** 手机筛选弹层:航班日期 / 航班号 / 特码(默认空 → 不进请求) */ + val flightDate = MutableLiveData("") + val flightNo = MutableLiveData("") + val spCode = MutableLiveData("") + val spCodeList = MutableLiveData>(emptyList()) + + val moveStateTabs = MutableLiveData( + listOf(KeyValue("待移库", "0"), KeyValue("已移库", "1")) + ) + + /** 状态 Tab 角标(与 [moveStateTabs] 等长,取两端点分页 total) */ + val moveStateCounts = MutableLiveData(listOf("", "")) + + /** 底部操作条「已选 N 项」 */ + val selectedCount = MutableLiveData("0") + + /** 全选状态(手机 PhoneBottomBar 勾选图标) */ + val isAllChecked = MutableLiveData(false) + + /** 手机专属的额外请求(Tab 角标、特码字典)开关,仅手机形态在 Activity 中开启 */ + private var phoneExtrasEnabled = false + + fun initPhoneExtras() { + phoneExtrasEnabled = true + // 特码字典:flag=0 国内、ieFlag=I 进港(是否生效待实测,见问题清单) + DictUtils.getSpecialCodeList(addAll = false, flag = 0, ieFlag = "I") { list -> + spCodeList.postValue(listOf(KeyValue("全部", "")) + list) + } + } + /////////////////////////////////////////////////////////////////////////// // 方法区 /////////////////////////////////////////////////////////////////////////// @@ -95,25 +130,73 @@ class GnjMoveStashListViewModel : BasePageViewModel() { } + /** 查询条件(分页参数除外),search / searchMoved / searchTotal 三处共用同一套入参 */ + private fun buildFilterParams(): Map = mapOf( + "awbType" to businessType.value!!.ifEmpty { null }, + "wbNo" to waybill.value!!.ifEmpty { null }, + "carrier" to carrier.value!!.ifEmpty { null }, + // 以下为手机筛选弹层字段,平板恒为空串 → 恒传 null,行为不变 + "fdate" to flightDate.value?.ifEmpty { null }, + "fno" to flightNo.value?.ifEmpty { null }, + "spCode" to spCode.value?.ifEmpty { null }, + ) + override fun getData() { - val body = mapOf( + val body = (buildFilterParams() + mapOf( "page" to pageModel.page, "limit" to pageModel.limit, - "awbType" to businessType.value!!.ifEmpty { null }, - "wbNo" to waybill.value!!.ifEmpty { null }, - "carrier" to carrier.value!!.ifEmpty { null }, - ).toRequestBody() + )).toRequestBody() + val moved = moveState.value == "1" launchLoadingCollect({ - NetApply.api.getGnjMoveStashList( - body - ) + // 平板 moveState 恒为 "0" → 恒走 search(原行为);已移库 Tab 走 searchMoved + if (moved) NetApply.api.getGnjMoveStashMovedList(body) + else NetApply.api.getGnjMoveStashList(body) }) { onSuccess = { - pageModel.handleListBean(it) + // searchMoved 出参无移库标识,按端点打标(卡片形态/详情移库信息卡依赖) + it.list?.forEach { bean -> bean.isMoved = moved } + pageModel.handleListBean(it) { updateCheckAllStatus() } count.value = it.total } } getCountData(body) + if (phoneExtrasEnabled) loadTabCounts() + } + + /** Tab 角标:search / searchMoved 各以 limit=1 查一次取分页 total(仅手机形态发起) */ + private fun loadTabCounts() { + val body = (buildFilterParams() + mapOf("page" to 1, "limit" to 1)).toRequestBody() + launchCollect({ NetApply.api.getGnjMoveStashList(body) }) { + onSuccess = { updateTabCount(0, it.total) } + } + launchCollect({ NetApply.api.getGnjMoveStashMovedList(body) }) { + onSuccess = { updateTabCount(1, it.total) } + } + } + + private fun updateTabCount(index: Int, total: Int?) { + val current = moveStateCounts.value?.toMutableList() ?: mutableListOf("", "") + if (index < current.size) { + current[index] = (total ?: 0).toString() + moveStateCounts.value = current + } + } + + // ========== 手机端全选 / 已选计数 ========== + + fun toggleSelectAll() { + val list = pageModel.rv?.commonAdapter()?.items + ?.filterIsInstance() ?: return + CheckUtil.handleAllCheck(list) + updateCheckAllStatus() + pageModel.rv?.commonAdapter()?.notifyDataSetChanged() + } + + 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() } private fun getCountData(body: RequestBody) { diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoActivity.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoActivity.kt new file mode 100644 index 0000000..971cb30 --- /dev/null +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoActivity.kt @@ -0,0 +1,45 @@ +package com.lukouguoji.aerologic.page.gnj.move.stash.photo + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.lukouguoji.aerologic.R +import com.lukouguoji.aerologic.databinding.ActivityGnjMoveStashPhotoBinding +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.ktx.addOnItemClickListener + +/** + * 国内进港移库「拍照上传」(5.5 寸手持端专属页面,无平板变体) + * + * 由列表卡片长按浮层「拍照」或运单详情「异常照片」加号槽位进入。 + * 已有照片经 DomImpMove/detail 回填,提交走 DomImpMove/modify + * (mawbId + pic/originalPic/picNumber 三字段规范,与平板移交编辑页同一链路)。 + */ +class GnjMoveStashPhotoActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_gnj_move_stash_photo + override fun viewModelClass() = GnjMoveStashPhotoViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("拍照上传") + binding.viewModel = viewModel + + viewModel.rv = binding.rv + binding.rv.addOnItemClickListener(viewModel) + + viewModel.initOnCreated(intent) + } + + companion object { + @JvmStatic + fun start(context: Context, mawbId: String, wbNo: String) { + context.startActivity( + Intent(context, GnjMoveStashPhotoActivity::class.java) + .putExtra(Constant.Key.ID, mawbId) + .putExtra(Constant.Key.CODE, wbNo) + ) + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMovePhotoViewModel.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoViewModel.kt similarity index 61% rename from module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMovePhotoViewModel.kt rename to app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoViewModel.kt index 98a4cdd..9ad8f53 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMovePhotoViewModel.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoViewModel.kt @@ -1,19 +1,20 @@ -package com.lukouguoji.gjj.viewModel +package com.lukouguoji.aerologic.page.gnj.move.stash.photo import android.content.Intent import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import androidx.recyclerview.widget.RecyclerView -import com.google.gson.Gson -import com.lukouguoji.gjj.R import com.lukouguoji.module_base.base.BaseViewModel import com.lukouguoji.module_base.bean.FileBean -import com.lukouguoji.module_base.bean.IntImpMoveBean +import com.lukouguoji.module_base.bean.GnjYiKuBean import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.common.ConstantEvent import com.lukouguoji.module_base.http.net.NetApply +import com.lukouguoji.module_base.impl.FlowBus import com.lukouguoji.module_base.impl.ImageSelectNewViewHolder import com.lukouguoji.module_base.interfaces.IOnItemClickListener import com.lukouguoji.module_base.ktx.commonAdapter +import com.lukouguoji.module_base.ktx.launchCollect import com.lukouguoji.module_base.ktx.launchLoadingCollect import com.lukouguoji.module_base.ktx.noNull import com.lukouguoji.module_base.ktx.showToast @@ -30,17 +31,24 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.launch /** - * 国际进港移库「拍照上传」ViewModel(5.5 寸手持端专属页面) + * 国内进港移库「拍照上传」ViewModel(5.5 寸手持端专属页面) * * 图片选择/预览/删除复用 module_base 的 ImageSelectNewViewHolder(末位加号槽位)。 - * 提交走三字段规范(pic 缩略图 / originalPic 原图 / picNumber 数量)。 - * ⚠️ 后端暂无 IntImpMove 模块,提交接口按约定预接(问题清单已登记)。 + * 已有照片经 DomImpMove/detail 回填;提交走 DomImpMove/modify 最小体 + * (mawbId/remark/picNumber/pic/originalPic),与平板移交编辑页同一链路。 */ -class IntImpMovePhotoViewModel : BaseViewModel(), IOnItemClickListener { +class GnjMoveStashPhotoViewModel : BaseViewModel(), IOnItemClickListener { - val dataBean = MutableLiveData(IntImpMoveBean()) + var mawbId = "" + + /** 运单号(副标题展示,由列表带入) */ + val wbNo = MutableLiveData("") + + /** detail 回填的完整 bean(提交时保留 remark 等原值) */ + private var detailBean = GnjYiKuBean() // 图片网格适配器配置(复用公共图片选择组件) val itemViewHolder = ImageSelectNewViewHolder::class.java @@ -49,29 +57,35 @@ class IntImpMovePhotoViewModel : BaseViewModel(), IOnItemClickListener { var rv: RecyclerView? = null fun initOnCreated(intent: Intent) { - val json = intent.getStringExtra(Constant.Key.DATA).orEmpty() - if (json.isNotEmpty()) { - dataBean.value = Gson().fromJson(json, IntImpMoveBean::class.java) - } + mawbId = intent.getStringExtra(Constant.Key.ID).orEmpty() + wbNo.value = intent.getStringExtra(Constant.Key.CODE).orEmpty() // 已有照片回填(pic 缩略图 + originalPic 原图),末位补加号槽位 - val bean = dataBean.value ?: IntImpMoveBean() - val picList = bean.pic.split(",").filter { it.isNotEmpty() } - val originalList = bean.originalPic.split(",").filter { it.isNotEmpty() } - val images = picList.mapIndexed { index, picUrl -> - FileBean( - path = MediaUtil.fillUrl(picUrl), - url = picUrl, - originalPic = MediaUtil.fillUrl(originalList.getOrElse(index) { picUrl }) - ) - } - rv?.post { - rv?.commonAdapter()?.refresh(images + FileBean()) + launchCollect({ NetApply.api.getGnjMoveStashDetail(mawbId) }) { + onSuccess = { + detailBean = it.data ?: GnjYiKuBean() + val picList = detailBean.pic.split(",").filter { p -> p.isNotEmpty() } + val originalList = detailBean.originalPic.split(",").filter { p -> p.isNotEmpty() } + val images = picList.mapIndexed { index, picUrl -> + FileBean( + path = MediaUtil.fillUrl(picUrl), + url = picUrl, + originalPic = MediaUtil.fillUrl(originalList.getOrElse(index) { picUrl }) + ) + } + rv?.post { + rv?.commonAdapter()?.refresh(images + FileBean()) + } + } + onFailed = { _, _ -> + // 详情取不到也允许直接新增照片 + rv?.post { rv?.commonAdapter()?.refresh(listOf(FileBean())) } + } } } /** - * 确认提交:先补传未上传的本地图片,再按三字段规范提交 + * 确认提交:先补传未上传的本地图片,再按三字段规范提交 modify */ fun submitClick() { (rv?.commonAdapter()?.items ?: emptyList()) @@ -95,15 +109,23 @@ class IntImpMovePhotoViewModel : BaseViewModel(), IOnItemClickListener { val list = (rv?.commonAdapter()?.items ?: emptyList()) .filterIsInstance() .filter { it.path.isNotEmpty() } - val bean = dataBean.value!! - bean.picNumber = list.size.toString() - bean.pic = list.joinToString(",") { MediaUtil.removeUrl(it.url) } - bean.originalPic = list.joinToString(",") { MediaUtil.removeUrl(it.originalPic) } - NetApply.api.submitIntImpMovePic(bean.toRequestBody()) + // 最小体提交:只更新图片三字段(remark 保留 detail 原值),与平板移交编辑页一致 + val params = mapOf( + "mawbId" to mawbId, + "remark" to detailBean.remark, + "picNumber" to list.size.toString(), + "pic" to list.joinToString(",") { MediaUtil.removeUrl(it.url) }, + "originalPic" to list.joinToString(",") { MediaUtil.removeUrl(it.originalPic) }, + ).toRequestBody(removeEmptyOrNull = true) + + NetApply.api.modifyGnjMoveStash(params) }) { onSuccess = { showToast("提交成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } getTopActivity().finish() } onFailed = { _, msg -> diff --git a/app/src/main/res/layout-sw600dp/activity_gnj_move_stash_list.xml b/app/src/main/res/layout-sw600dp/activity_gnj_move_stash_list.xml new file mode 100644 index 0000000..7582268 --- /dev/null +++ b/app/src/main/res/layout-sw600dp/activity_gnj_move_stash_list.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-sw600dp/item_gnj_move_stash_list.xml b/app/src/main/res/layout-sw600dp/item_gnj_move_stash_list.xml new file mode 100644 index 0000000..b8a56ac --- /dev/null +++ b/app/src/main/res/layout-sw600dp/item_gnj_move_stash_list.xml @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/activity_int_imp_move_detail.xml b/app/src/main/res/layout/activity_gnj_move_stash_detail.xml similarity index 93% rename from module_gjj/src/main/res/layout/activity_int_imp_move_detail.xml rename to app/src/main/res/layout/activity_gnj_move_stash_detail.xml index 1f3d243..bd97b5a 100644 --- a/module_gjj/src/main/res/layout/activity_int_imp_move_detail.xml +++ b/app/src/main/res/layout/activity_gnj_move_stash_detail.xml @@ -1,14 +1,12 @@ @@ -19,11 +17,11 @@ + type="com.lukouguoji.aerologic.page.gnj.move.stash.detail.GnjMoveStashDetailViewModel" /> + type="com.lukouguoji.aerologic.page.gnj.move.stash.detail.GnjMoveStashDetailActivity" /> - + @@ -94,7 +92,7 @@ android:orientation="vertical" android:padding="16dp"> - + @@ -122,7 +120,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.businessName.empty ? viewModel.dataBean.businessType : viewModel.dataBean.businessName)}" + android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.cargoType)}" android:textColor="@color/phone_text_body" android:textSize="14sp" /> @@ -134,7 +132,7 @@ android:layout_height="wrap_content" android:layout_marginTop="12dp" android:layout_marginBottom="12dp" - android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.goodsName)}" + android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.goods)}" android:textColor="@color/phone_text_strong" android:textSize="22sp" android:textStyle="bold" /> @@ -150,7 +148,7 @@ android:layout_height="wrap_content" android:layout_weight="1" title='@{"件数"}' - value="@{String.valueOf(viewModel.dataBean.pc)}" /> + value="@{viewModel.dataBean.orDash(viewModel.dataBean.pc)}" /> + value='@{viewModel.dataBean.orDash(viewModel.dataBean.weight) + " kg"}' /> @@ -182,7 +180,7 @@ android:layout_marginStart="32dp" android:layout_weight="1" title='@{"代理"}' - value="@{viewModel.dataBean.agentName.empty ? viewModel.dataBean.agentCode : viewModel.dataBean.agentName}" /> + value="@{viewModel.dataBean.agentDisplay}" /> @@ -254,7 +252,7 @@ android:layout_marginStart="32dp" android:layout_weight="1" title='@{"移库时间"}' - value="@{viewModel.dataBean.opdate}" /> + value="@{viewModel.dataBean.opDate}" /> diff --git a/app/src/main/res/layout/activity_gnj_move_stash_list.xml b/app/src/main/res/layout/activity_gnj_move_stash_list.xml index 1e068ef..9b9a057 100644 --- a/app/src/main/res/layout/activity_gnj_move_stash_list.xml +++ b/app/src/main/res/layout/activity_gnj_move_stash_list.xml @@ -1,148 +1,166 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/activity_int_imp_move_photo.xml b/app/src/main/res/layout/activity_gnj_move_stash_photo.xml similarity index 93% rename from module_gjj/src/main/res/layout/activity_int_imp_move_photo.xml rename to app/src/main/res/layout/activity_gnj_move_stash_photo.xml index 2b6a422..67215c8 100644 --- a/module_gjj/src/main/res/layout/activity_int_imp_move_photo.xml +++ b/app/src/main/res/layout/activity_gnj_move_stash_photo.xml @@ -1,12 +1,12 @@ + type="com.lukouguoji.aerologic.page.gnj.move.stash.photo.GnjMoveStashPhotoViewModel" /> diff --git a/app/src/main/res/layout/item_gnj_move_stash_list.xml b/app/src/main/res/layout/item_gnj_move_stash_list.xml index 907131a..6b2f863 100644 --- a/app/src/main/res/layout/item_gnj_move_stash_list.xml +++ b/app/src/main/res/layout/item_gnj_move_stash_list.xml @@ -1,287 +1,227 @@ + + + + + + + - - + android:layout_marginHorizontal="12dp" + android:layout_marginTop="12dp"> - - + android:layout_height="wrap_content" + android:background="@drawable/bg_phone_card" + android:onLongClick="@{()-> activity.showCardActionPhone(bean)}" + android:orientation="vertical" + android:padding="16dp"> - - + + android:gravity="center_vertical" + android:orientation="horizontal"> + + android:layout_width="20dp" + android:layout_height="20dp" + android:layout_marginEnd="8dp" + android:src="@drawable/ic_phone_check_round_unchecked" + android:visibility="@{bean.isMoved ? View.GONE : View.VISIBLE}" + loadImage="@{bean.checked.get() ? @drawable/ic_phone_check_round_checked : @drawable/ic_phone_check_round_unchecked}" /> - + + android:text="@{bean.wbNo}" + android:textColor="@{bean.isMoved ? @color/phone_text_title : @color/phone_primary}" + android:textSize="15sp" + android:textStyle="bold" /> - + + - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_marginStart="4dp" + android:text="已移库" + android:textColor="@color/phone_text_title" + android:textSize="13sp" /> - - + - - - - + - + + + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="4dp" + android:layout_weight="1" + android:text='@{"航班信息:" + bean.orDash(bean.flight)}' + android:textColor="@color/phone_text_body" + android:textSize="13sp" + tools:text="航班信息:20260709/MU2311" /> - + - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documents/后端接口对接问题清单.xlsx b/documents/后端接口对接问题清单.xlsx index c6cab51de3835cb54fc351b84d9d04618f9a8227..fd2b823f3a6ef4d5a30cf65c40550e4840acb7cc 100644 GIT binary patch delta 13597 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 Rnbc0&&?bW**8Pv`{{TyMb2R_} delta 12501 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%0A@v+T#po6L4BMQ45jbma8Tfs(=M2pUE1h-qny8 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 Hga7{k|1)4- diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpMoveBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpMoveBean.kt deleted file mode 100644 index e800406..0000000 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpMoveBean.kt +++ /dev/null @@ -1,78 +0,0 @@ -package com.lukouguoji.module_base.bean - -import androidx.databinding.ObservableBoolean -import com.lukouguoji.module_base.interfaces.ICheck -import java.io.Serializable - -/** - * 国际进港移库 Bean(5.5 寸手持端专属页面) - * - * ⚠️ 后端目前**没有**「国际进港移库」模块(api-doc 仅有国内进港 DomImpMove 与国际出港 IntExpMove, - * 2026-07-31 核对),字段按 IntExpMove 出参约定 + 设计稿展示需求镜像定义, - * 已登记《后端接口对接问题清单》。后端按同名约定交付后前端自动生效。 - */ -data class IntImpMoveBean( - var no: String = "", // 运单号主体 - var prefix: String = "", // 运单前缀 - var wbNo: String = "", // 运单号 - var pc: Long = 0, // 件数 - var weight: Double = 0.0, // 重量 - - var fdate: String = "", // 航班日期 - var fno: String = "", // 航班号 - var flight: String = "", // 航班信息(日期/航班号 组合串) - var range: String = "", // 出运路径(如 HFE-NKG-LAX) - - var by1: String = "", // 承运人 - var awbType: String = "", // 运单类型编码 - var awbTypeName: String = "", // 运单类型名称 - var businessType: String = "", // 业务类型编码 - var businessName: String = "", // 业务类型名称 - var moveState: Int = 0, // 移库状态(0-待移库,1-已移库) - var goods: String = "", // 品名(英文) - var goodsCn: String = "", // 品名(中文) - var agentName: String = "", // 代理人 - var agentCode: String = "", // 代理代码 - var spCode: String = "", // 特码 - - var maWbId: Long = 0, // 主单主键ID - var opId: String = "", // 移库人 - var opdate: String = "", // 移库时间 - var remark: String = "", // 备注 - - // 异常照片(拍照上传,三字段规范:pic 缩略图 / originalPic 原图 / picNumber 数量) - var pic: String = "", - var originalPic: String = "", - var picNumber: String = "", - - // UI扩展字段 - 使用ObservableBoolean实现自动UI更新 - val checked: ObservableBoolean = ObservableBoolean(false), - // 卡片长按操作浮层显隐(仅 UI 状态) - val actionMenuVisible: ObservableBoolean = ObservableBoolean(false) -) : Serializable, ICheck { - - override fun getCheckObservable(): ObservableBoolean = checked - - var isSelected: Boolean - get() = checked.get() - set(value) = checked.set(value) - - // ========== 5.5 寸手持端展示辅助字段(仅用于手机版布局,不参与序列化) ========== - - /** 是否已移库(moveState:0-待移库,1-已移库) */ - val isMoved: Boolean - get() = moveState == 1 - - /** 品名:优先中文,为空回退英文 */ - val goodsName: String - get() = goodsCn.ifEmpty { goods } - - /** 航班信息展示:优先组合串,其次 日期/航班号 拼接 */ - val flightInfo: String - get() = flight.ifEmpty { - if (fdate.isEmpty() && fno.isEmpty()) "" else "$fdate/$fno" - } - - /** 详情页字段统一空值占位 */ - fun orDash(value: String?): String = if (value.isNullOrEmpty()) "-" else value -} diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/MoveStashBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/MoveStashBean.kt index 8c151b9..34bdc63 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/MoveStashBean.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/MoveStashBean.kt @@ -6,6 +6,7 @@ import com.lukouguoji.module_base.interfaces.ICheck class MoveStashBean : ICheck { var activeId: String = "" // null var agentCode: String = "" // HFEXB + var agentName: String = "" // 代理人名称(search 出参有定义) var awbType: String = "" // 国际进港(国内中转) var businessType: String = "" // null var by1: String = "" // null @@ -49,4 +50,19 @@ class MoveStashBean : ICheck { override fun getCheckObservable(): ObservableBoolean { return checked } + + // ========== 5.5 寸手持端展示辅助字段(仅前端使用,不参与提交) ========== + + /** 是否已移库:由列表加载端点决定(search=待移库 / searchMoved=已移库),载入时打标 */ + var isMoved: Boolean = false + + /** 卡片长按「拍照」操作浮层显隐(仅 UI 状态) */ + val actionMenuVisible = ObservableBoolean(false) + + /** 代理显示:网络层会把 null 归一成空串,须 isNullOrEmpty 双兜底(沿用进港/出港查询口径) */ + val agentDisplay: String + get() = if (agentName.isNotEmpty()) agentName else agentCode + + /** 详情页/卡片字段统一空值占位 */ + fun orDash(value: String?): String = if (value.isNullOrEmpty()) "-" else value } \ No newline at end of file diff --git a/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt b/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt index 9e23ac2..d343bce 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt @@ -274,7 +274,6 @@ interface Constant { const val IntImpPickUpDLV = "AppIntImpPickUpDLV" //提取出库 // 进港移库:后端暂无该模块与权限串(2026-07-31 api-doc 核对),按 AppIntImp* 命名约定预定义, // 权限串下发前手机首页菜单不会显示该入口(已登记后端接口对接问题清单) - const val IntImpMove = "AppIntImpMove" //进港移库 const val IntImpAccidentVisa = "AppIntImpAccidentVisa" //事故签证 const val GjjManifestListActivity = "AppIntExpManifest" //舱单 const val GjjTallyListActivity = "AppIntExpTally" //理货 diff --git a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt index ba750f0..00d6ad5 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt @@ -55,7 +55,6 @@ import com.lukouguoji.module_base.bean.GjAccidentVisaEditBean import com.lukouguoji.module_base.bean.IntImpAccidentVisaBean import com.lukouguoji.module_base.bean.IntImpPickUpDLVBean import com.lukouguoji.module_base.bean.IntImpPickUpRecordBean -import com.lukouguoji.module_base.bean.IntImpMoveBean import com.lukouguoji.module_base.bean.IntImpQueryBean import com.lukouguoji.module_base.bean.GjjManifest import com.lukouguoji.module_base.bean.GjjManifestBean @@ -883,38 +882,6 @@ interface Api { @POST("IntExpMove/move") suspend fun submitIntExpMove(@Body data: RequestBody): BaseResultBean - /** - * 国际进港移库-分页查询 - * 接口路径: /IntImpMove/pageQuery - * ⚠️ 后端暂无该模块(2026-07-31 api-doc 核对),按 IntExpMove 命名约定预接,已登记问题清单 - */ - @POST("IntImpMove/pageQuery") - suspend fun getIntImpMoveList(@Body data: RequestBody): BaseListBean - - /** - * 国际进港移库-分页合计 - * 接口路径: /IntImpMove/pageQueryTotal - * ⚠️ 后端暂无该模块,同上 - */ - @POST("IntImpMove/pageQueryTotal") - suspend fun getIntImpMoveTotal(@Body data: RequestBody): BaseResultBean - - /** - * 国际进港移库-批量移库 - * 接口路径: /IntImpMove/move - * ⚠️ 后端暂无该模块,同上 - */ - @POST("IntImpMove/move") - suspend fun submitIntImpMove(@Body data: RequestBody): BaseResultBean - - /** - * 国际进港移库-异常照片上传(pic/originalPic/picNumber 三字段规范) - * 接口路径: /IntImpMove/uploadPic - * ⚠️ 后端暂无该模块,同上 - */ - @POST("IntImpMove/uploadPic") - suspend fun submitIntImpMovePic(@Body data: RequestBody): BaseResultBean - /** * 国际出港库位操作-清仓 * 接口路径: /IntExpStorageUse/updateClear @@ -1799,6 +1766,12 @@ interface Api { @POST("DomImpMove/search") suspend fun getGnjMoveStashList(@Body data: RequestBody): BaseListBean + /** + * 获取-国内进港移库-已移库列表(移库完成分页搜索,5.5 寸手机端「已移库」Tab) + */ + @POST("DomImpMove/searchMoved") + suspend fun getGnjMoveStashMovedList(@Body data: RequestBody): BaseListBean + /** * 获取-国内进港移库-列表--运单列表 */ 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 1a87ea1..8dd2500 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 @@ -104,6 +104,7 @@ object ARouterConstants { // 国内进港移库(新版本) const val ACTIVITY_URL_GNJ_YIKU_LIST = "/gnj/GnjYiKuListActivity" //国内进港 移库列表 + const val ACTIVITY_URL_GNJ_MOVE_STASH_LIST = "/app/GnjMoveStashListActivity" //国内进港 移库(首页菜单实际跳转页,双形态) const val ACTIVITY_URL_GNJ_YIKU_DETAILS = "/gnj/GnjYiKuDetailsActivity" //国内进港 移库详情 const val ACTIVITY_URL_GNJ_YIKU_EDIT = "/gnj/GnjYiKuEditActivity" //国内进港 移库编辑 const val ACTIVITY_URL_GNJ_YIKU_HANDOVER = "/gnj/GnjYiKuHandoverActivity" //国内进港 移交编辑/详情 @@ -182,7 +183,6 @@ object ARouterConstants { const val ACTIVITY_URL_INT_IMP_LOADING_LIST = "/gjj/IntImpLoadingListActivity" //国际进港 装机单(分拣理货) const val ACTIVITY_URL_INT_IMP_TALLY = "/gjj/IntImpTallyActivity" //国际进港 理货报告 const val ACTIVITY_URL_INT_IMP_PICK_UP_DLV = "/gjj/IntImpPickUpDLVActivity" //国际进港 提取出库 - const val ACTIVITY_URL_INT_IMP_MOVE = "/gjj/IntImpMoveActivity" //国际进港 进港移库(5.5寸手机端专属页) const val ACTIVITY_URL_INT_IMP_ACCIDENT_VISA = "/gjj/IntImpAccidentVisaActivity" //国际进港 事故签证 ///////////////// 航班查询模块 diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveActivity.kt deleted file mode 100644 index 6642ad0..0000000 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveActivity.kt +++ /dev/null @@ -1,147 +0,0 @@ -package com.lukouguoji.gjj.activity - -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.os.Bundle -import androidx.databinding.ObservableBoolean -import com.alibaba.android.arouter.facade.annotation.Route -import com.lukouguoji.gjj.R -import com.lukouguoji.gjj.databinding.ActivityIntImpMoveBinding -import com.lukouguoji.gjj.viewModel.IntImpMoveViewModel -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.bean.IntImpMoveBean -import com.lukouguoji.module_base.common.Constant -import com.lukouguoji.module_base.common.ConstantEvent -import com.lukouguoji.module_base.impl.FlowBus -import com.lukouguoji.module_base.impl.observe -import com.lukouguoji.module_base.ktx.addOnItemClickListener -import com.lukouguoji.module_base.ktx.showToast -import com.lukouguoji.module_base.model.ConfirmDialogModel -import com.lukouguoji.module_base.model.ScanModel -import com.lukouguoji.module_base.router.ARouterConstants - -/** - * 国际进港-进港移库(5.5 寸手持端专属页面,无平板版本) - * - * 结构镜像 IntExpMoveActivity(国际出港移库),另有卡片长按「拍照」浮层(设计稿新增交互)。 - * ⚠️ 后端目前没有 IntImpMove 模块,接口按同名约定预接(问题清单已登记)。 - */ -@Route(path = ARouterConstants.ACTIVITY_URL_INT_IMP_MOVE) -class IntImpMoveActivity : BaseBindingActivity() { - - override fun layoutId() = R.layout.activity_int_imp_move - - override fun viewModelClass() = IntImpMoveViewModel::class.java - - /** 筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ - val filterPanelVisible = ObservableBoolean(false) - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("进港移库") - binding.viewModel = viewModel - binding.activity = this - - viewModel.initDictLists() - - viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this) - binding.rv.addOnItemClickListener(viewModel) - - // 监听item选择变化事件,更新全选状态 - FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { - viewModel.onItemCheckChanged() - } - - // 监听刷新事件 - FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) { - viewModel.refresh() - } - - viewModel.refresh() - } - - /** - * 扫码运单号 - */ - fun scanWaybill() { - ScanModel.startScan(this, Constant.RequestCode.WAYBILL) - } - - // ==================== 筛选弹层 ==================== - - fun toggleFilterPanel() { - filterPanelVisible.set(!filterPanelVisible.get()) - } - - /** - * 筛选:重置(只清空弹层内条件,不影响 Tab 与顶部搜索框) - */ - fun resetFilter() { - viewModel.flightDate.value = "" - viewModel.flightNo.value = "" - viewModel.spCode.value = "" - viewModel.awbType.value = "" - } - - fun confirmFilter() { - filterPanelVisible.set(false) - viewModel.searchClick() - } - - // ==================== 卡片长按「拍照」浮层 ==================== - - /** 卡片长按:展开操作浮层(View.OnLongClickListener 要求返回 Boolean) */ - fun showCardActionPhone(bean: IntImpMoveBean): Boolean { - bean.actionMenuVisible.set(true) - return true - } - - /** 点浮层空白处关闭 */ - fun hideCardActionPhone(bean: IntImpMoveBean) { - bean.actionMenuVisible.set(false) - } - - /** 浮层「拍照」→ 拍照上传页 */ - fun openPhoto(bean: IntImpMoveBean) { - bean.actionMenuVisible.set(false) - IntImpMovePhotoActivity.start(this, bean) - } - - /** - * 显示移库确认对话框(底部操作条 setOnActionClick 调用) - */ - fun showMoveConfirmDialog() { - val selectedItems = viewModel.getSelectedItems() - - if (selectedItems.isEmpty()) { - showToast("请至少选择一条运单") - return - } - - ConfirmDialogModel( - message = "确定要移库选中的 ${selectedItems.size} 条运单吗?", - title = "移库确认" - ) { - viewModel.submitMove() - }.show() - } - - /** - * 扫码回调 - */ - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - if (requestCode == Constant.RequestCode.WAYBILL && resultCode == Activity.RESULT_OK) { - val code = data?.getStringExtra(Constant.Result.CODED_CONTENT) - viewModel.waybillNo.value = code - viewModel.searchClick() - } - } - - companion object { - @JvmStatic - fun start(context: Context) { - context.startActivity(Intent(context, IntImpMoveActivity::class.java)) - } - } -} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveDetailActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveDetailActivity.kt deleted file mode 100644 index 183ac90..0000000 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveDetailActivity.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.lukouguoji.gjj.activity - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import com.google.gson.Gson -import com.lukouguoji.gjj.R -import com.lukouguoji.gjj.databinding.ActivityIntImpMoveDetailBinding -import com.lukouguoji.gjj.viewModel.IntImpMoveDetailViewModel -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.bean.IntImpMoveBean -import com.lukouguoji.module_base.common.Constant - -/** - * 国际进港移库「运单详情」(5.5 寸手持端专属页面) - * - * 由列表卡片的「查看详情」进入;「异常照片」卡片的加号槽位跳拍照上传页。 - */ -class IntImpMoveDetailActivity : - BaseBindingActivity() { - - override fun layoutId() = R.layout.activity_int_imp_move_detail - override fun viewModelClass() = IntImpMoveDetailViewModel::class.java - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("运单详情") - binding.viewModel = viewModel - binding.activity = this - viewModel.initOnCreated(intent) - } - - /** 「异常照片」加号槽位 → 拍照上传页 */ - fun openPhoto() { - viewModel.dataBean.value?.let { IntImpMovePhotoActivity.start(this, it) } - } - - companion object { - @JvmStatic - fun start(context: Context, bean: IntImpMoveBean) { - context.startActivity( - Intent(context, IntImpMoveDetailActivity::class.java) - .putExtra(Constant.Key.DATA, Gson().toJson(bean)) - ) - } - } -} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMovePhotoActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMovePhotoActivity.kt deleted file mode 100644 index 40aba03..0000000 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMovePhotoActivity.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.lukouguoji.gjj.activity - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import com.google.gson.Gson -import com.lukouguoji.gjj.R -import com.lukouguoji.gjj.databinding.ActivityIntImpMovePhotoBinding -import com.lukouguoji.gjj.viewModel.IntImpMovePhotoViewModel -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.bean.IntImpMoveBean -import com.lukouguoji.module_base.common.Constant -import com.lukouguoji.module_base.ktx.addOnItemClickListener - -/** - * 国际进港移库「拍照上传」(5.5 寸手持端专属页面) - * - * 由列表卡片长按浮层「拍照」或运单详情「异常照片」加号槽位进入。 - */ -class IntImpMovePhotoActivity : - BaseBindingActivity() { - - override fun layoutId() = R.layout.activity_int_imp_move_photo - override fun viewModelClass() = IntImpMovePhotoViewModel::class.java - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("拍照上传") - binding.viewModel = viewModel - - viewModel.rv = binding.rv - binding.rv.addOnItemClickListener(viewModel) - - viewModel.initOnCreated(intent) - } - - companion object { - @JvmStatic - fun start(context: Context, bean: IntImpMoveBean) { - context.startActivity( - Intent(context, IntImpMovePhotoActivity::class.java) - .putExtra(Constant.Key.DATA, Gson().toJson(bean)) - ) - } - } -} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpMoveViewHolder.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpMoveViewHolder.kt deleted file mode 100644 index 20aa602..0000000 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpMoveViewHolder.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.lukouguoji.gjj.holder - -import android.view.View -import com.lukouguoji.gjj.activity.IntImpMoveActivity -import com.lukouguoji.gjj.activity.IntImpMoveDetailActivity -import com.lukouguoji.gjj.databinding.ItemIntImpMoveBinding -import com.lukouguoji.module_base.base.BaseViewHolder -import com.lukouguoji.module_base.bean.IntImpMoveBean -import com.lukouguoji.module_base.common.ConstantEvent -import com.lukouguoji.module_base.impl.FlowBus -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch - -/** - * 国际进港移库列表项 ViewHolder(5.5 寸手持端专属页面) - * - * 卡片交互: - * · 勾选框点击 → 切换选中并通知 Activity 更新全选/已选计数 - * · 「查看详情」→ 运单详情页 - * · 卡片长按 → 「拍照」操作浮层(XML 绑定 activity 回调) - */ -class IntImpMoveViewHolder(view: View) : - BaseViewHolder(view) { - - override fun onBind(item: Any?, position: Int) { - val bean = getItemBean(item) ?: return - binding.bean = bean - binding.position = position - binding.activity = itemView.context as? IntImpMoveActivity - - // 「查看详情」→ 运单详情页 - binding.llDetail.setOnClickListener { - IntImpMoveDetailActivity.start(itemView.context, bean) - } - - // 勾选框点击 - 切换选择状态 - binding.ivIcon.setOnClickListener { - bean.checked.set(!bean.checked.get()) - binding.executePendingBindings() - - GlobalScope.launch { - FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).emit("check_changed") - } - } - - binding.executePendingBindings() - } -} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveDetailViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveDetailViewModel.kt deleted file mode 100644 index 9154f69..0000000 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveDetailViewModel.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.lukouguoji.gjj.viewModel - -import android.content.Intent -import androidx.lifecycle.MutableLiveData -import com.google.gson.Gson -import com.lukouguoji.module_base.base.BaseViewModel -import com.lukouguoji.module_base.bean.IntImpMoveBean -import com.lukouguoji.module_base.common.Constant - -/** - * 国际进港移库「运单详情」ViewModel(5.5 寸手持端专属页面) - * - * 列表项数据已包含详情页所需全部字段,故直接由列表带入,不额外请求接口 - * (后端暂无 IntImpMove 模块,也没有 detail 接口可查,问题清单已登记)。 - */ -class IntImpMoveDetailViewModel : BaseViewModel() { - - val dataBean = MutableLiveData(IntImpMoveBean()) - - fun initOnCreated(intent: Intent) { - val json = intent.getStringExtra(Constant.Key.DATA).orEmpty() - if (json.isNotEmpty()) { - dataBean.value = Gson().fromJson(json, IntImpMoveBean::class.java) - } - } -} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveViewModel.kt deleted file mode 100644 index e9bb2de..0000000 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveViewModel.kt +++ /dev/null @@ -1,187 +0,0 @@ -package com.lukouguoji.gjj.viewModel - -import androidx.lifecycle.MutableLiveData -import com.lukouguoji.gjj.R -import com.lukouguoji.gjj.holder.IntImpMoveViewHolder -import com.lukouguoji.module_base.base.BasePageViewModel -import com.lukouguoji.module_base.bean.IntImpMoveBean -import com.lukouguoji.module_base.http.net.NetApply -import com.lukouguoji.module_base.interfaces.IOnItemClickListener -import com.lukouguoji.module_base.ktx.commonAdapter -import com.lukouguoji.module_base.ktx.launchCollect -import com.lukouguoji.module_base.ktx.launchLoadingCollect -import com.lukouguoji.module_base.ktx.noNull -import com.lukouguoji.module_base.ktx.showToast -import com.lukouguoji.module_base.ktx.toRequestBody -import com.lukouguoji.module_base.util.CheckUtil -import com.lukouguoji.module_base.util.DictUtils -import dev.utils.app.info.KeyValue - -/** - * 国际进港移库 ViewModel(5.5 寸手持端专属页面,无平板版本) - * - * 结构镜像 IntExpMoveViewModel(国际出港移库)。 - * ⚠️ 后端目前没有 IntImpMove 模块(2026-07-31 api-doc 核对),接口按同名约定预接, - * 实机会请求失败(问题清单已登记),后端交付后自动生效。 - */ -class IntImpMoveViewModel : BasePageViewModel(), IOnItemClickListener { - - // ========== 搜索字段(设计稿筛选弹层:航班日期 / 航班号 / 特码 / 运单类型) ========== - val flightDate = MutableLiveData("") // 航班日期 - val flightNo = MutableLiveData("") // 航班号 - val spCode = MutableLiveData("") // 特码 - val awbType = MutableLiveData("") // 运单类型 - val moveState = MutableLiveData("0") // 移库状态(默认「待移库」Tab) - val waybillNo = MutableLiveData("") // 运单号 - - // ========== 下拉数据 ========== - val spCodeList = MutableLiveData>(emptyList()) - val awbTypeList = MutableLiveData>(emptyList()) - - /** 状态 Tab 配置(设计稿只有两个 Tab,无「全部」) */ - val moveStateTabs = MutableLiveData( - listOf(KeyValue("待移库", "0"), KeyValue("已移库", "1")) - ) - - /** 状态 Tab 角标(与 [moveStateTabs] 等长) */ - val moveStateCounts = MutableLiveData(listOf("", "")) - - /** 已选数量(底部操作条「已选 N 项」) */ - val selectedCount = MutableLiveData("0") - - // ========== 全选状态 ========== - val isAllChecked = MutableLiveData(false) - - // ========== 适配器配置 ========== - val itemViewHolder = IntImpMoveViewHolder::class.java - val itemLayoutId = R.layout.item_int_imp_move - - /** - * 初始化下拉字典(特码 + 运单类型,type=II 国际进港) - */ - fun initDictLists() { - // flag=1 国际;ieFlag 必须留空——传值后端返回空数组(与既有国际页面口径一致) - DictUtils.getSpecialCodeList(addAll = false, flag = 1, ieFlag = "") { list -> - spCodeList.postValue(listOf(KeyValue("全部", "")) + list) - } - DictUtils.getWaybillTypeList(type = "II", addAll = true) { - awbTypeList.postValue(it) - } - } - - fun searchClick() { - refresh() - } - - /** - * 全选/取消全选 - */ - fun toggleSelectAll() { - val adapter = pageModel.rv?.commonAdapter() ?: return - val list = adapter.items.filterIsInstance() - - CheckUtil.handleAllCheck(list) - updateCheckAllStatus() - adapter.notifyDataSetChanged() - } - - /** - * 更新全选状态与已选计数 - */ - fun updateCheckAllStatus() { - val adapter = pageModel.rv?.commonAdapter() ?: return - val list = adapter.items.filterIsInstance() - - isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() } - selectedCount.value = list.count { it.checked.get() }.toString() - } - - /** - * 单个item选择变化时调用(从Activity接收事件) - */ - fun onItemCheckChanged() { - updateCheckAllStatus() - } - - /** - * 获取选中的运单 - */ - fun getSelectedItems(): List { - val adapter = pageModel.rv?.commonAdapter() ?: return emptyList() - return adapter.items.filterIsInstance().filter { it.checked.get() } - } - - /** - * 提交移库(在Activity中显示确认对话框后调用) - */ - fun submitMove() { - val selectedItems = getSelectedItems() - - if (selectedItems.isEmpty()) { - showToast("请至少选择一条运单") - return - } - - launchLoadingCollect({ NetApply.api.submitIntImpMove(selectedItems.toRequestBody()) }) { - onSuccess = { - showToast("移库成功") - refresh() - } - onFailed = { _, msg -> - showToast(msg.noNull("移库失败")) - } - } - } - - /** - * 获取列表数据 - */ - override fun getData() { - // 构建筛选参数(只传递非空值;参数名按 IntExpMove 同名约定,待后端交付核对) - val filterParams = mutableMapOf() - - flightDate.value?.takeIf { it.isNotEmpty() }?.let { filterParams["fdate"] = it } - flightNo.value?.takeIf { it.isNotEmpty() }?.let { filterParams["fno"] = it } - spCode.value?.takeIf { it.isNotEmpty() }?.let { filterParams["spCode"] = it } - awbType.value?.takeIf { it.isNotEmpty() }?.let { filterParams["awbType"] = it } - moveState.value?.takeIf { it.isNotEmpty() }?.let { filterParams["moveState"] = it } - waybillNo.value?.takeIf { it.isNotEmpty() }?.let { filterParams["wbNo"] = it } - - val listParams = (filterParams + mapOf( - "pageNum" to pageModel.page, - "pageSize" to pageModel.limit - )).toRequestBody() - - launchLoadingCollect({ NetApply.api.getIntImpMoveList(listParams) }) { - onSuccess = { - pageModel.handleListBean(it) { updateCheckAllStatus() } - } - } - - // Tab 角标计数(复用统计接口,moveState=0/1 各查一次) - loadTabCounts(filterParams) - } - - private fun loadTabCounts(filterParams: Map) { - listOf("0", "1").forEachIndexed { index, state -> - val params = (filterParams + mapOf("moveState" to state)).toRequestBody() - launchCollect({ NetApply.api.getIntImpMoveTotal(params) }) { - onSuccess = { result -> - val count = (result.data?.wbNumber ?: 0).toString() - val current = moveStateCounts.value?.toMutableList() ?: mutableListOf("", "") - if (index < current.size) { - current[index] = count - moveStateCounts.value = current - } - } - } - } - } - - /** - * Item点击事件处理(点击已在ViewHolder中处理) - */ - override fun onItemClick(position: Int, type: Int) { - // 卡片交互均在 ViewHolder / XML 中处理 - } -} diff --git a/module_gjj/src/main/res/layout/activity_int_imp_move.xml b/module_gjj/src/main/res/layout/activity_int_imp_move.xml deleted file mode 100644 index c650e7c..0000000 --- a/module_gjj/src/main/res/layout/activity_int_imp_move.xml +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/module_gjj/src/main/res/layout/item_int_imp_move.xml b/module_gjj/src/main/res/layout/item_int_imp_move.xml deleted file mode 100644 index 38d6bdb..0000000 --- a/module_gjj/src/main/res/layout/item_int_imp_move.xml +++ /dev/null @@ -1,230 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 2348421..45b2972 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 @@ -78,14 +78,6 @@ class GjViewModel : BaseViewModel() { Constant.AuthName.GjjWareHouseActivity, ARouterConstants.ACTIVITY_URL_GJJ_WARE_HOUSE ), - // 进港移库:后端暂无该模块与权限串 AppIntImpMove(问题清单已登记), - // 权限串下发前此入口不会显示;实机验证走 debug 直启 - ActionBean( - "进港移库", - R.drawable.gjc_yi_ku_icon, // 复用出港移库图标(Pad 端无进港移库菜单) - Constant.AuthName.IntImpMove, - ARouterConstants.ACTIVITY_URL_INT_IMP_MOVE - ), ActionBean( "进港查询", R.drawable.gjj_query_icon, diff --git a/module_p/src/main/java/com/sixin/module_p/ui/enter/gn/GnViewModel.kt b/module_p/src/main/java/com/sixin/module_p/ui/enter/gn/GnViewModel.kt index c4873be..907c894 100644 --- a/module_p/src/main/java/com/sixin/module_p/ui/enter/gn/GnViewModel.kt +++ b/module_p/src/main/java/com/sixin/module_p/ui/enter/gn/GnViewModel.kt @@ -1,12 +1,14 @@ package com.sixin.module_p.ui.enter.gn import android.content.Intent +import com.alibaba.android.arouter.launcher.ARouter import com.lukouguoji.module_base.base.BaseViewModel import com.lukouguoji.module_base.bean.ActionBean import com.lukouguoji.module_base.common.Constant import com.lukouguoji.module_base.db.perference.SharedPreferenceUtil import com.lukouguoji.module_base.ktx.logd import com.lukouguoji.module_base.ktx.loge +import com.lukouguoji.module_base.router.ARouterConstants import com.sixin.module_p.R import com.sixin.module_p.ui.enter.gn.document.PdaDocumentHandoverActivity import com.sixin.module_p.ui.gnc.cunfang.list.PdaGncCunFangListActivity @@ -57,11 +59,25 @@ class GnViewModel : BaseViewModel() { R.mipmap.gnc_document_handover, Constant.AuthName.DocumentHandover ), + ActionBean( + "进港移库", + R.drawable.gnj_yi_ku_icon, // 图标复制自 module_gnj(module_p 看不到业务模块资源) + Constant.AuthName.GnjYiKu, // 权限串与 Pad 端菜单一致(AppDomImpMove) + ARouterConstants.ACTIVITY_URL_GNJ_MOVE_STASH_LIST // 与 Pad 首页菜单同一跳转页(app 模块,走路由) + ), ) .filter { SharedPreferenceUtil.getString(Constant.Share.authList).contains(it.key) } fun onItemClick(position: Int) { + val bean = actionList.getOrNull(position) ?: return + + // 配了路由的直接跳(5.5 寸适配页走这条,与 GjViewModel 同模式) + if (bean.route.isNotEmpty()) { + ARouter.getInstance().build(bean.route).navigation() + return + } + when (val title = actionList[position].title) { "出港收运" -> { GncUnShouYunActivity.start(DevUtils.getTopActivity()) diff --git a/module_p/src/main/res/drawable-xxhdpi/gnj_yi_ku_icon.png b/module_p/src/main/res/drawable-xxhdpi/gnj_yi_ku_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..26454c68eca0c13ef996fbcf26e45cc563be78fc GIT binary patch literal 26578 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 Date: Thu, 6 Aug 2026 10:26:23 +0800 Subject: [PATCH 13/29] feat: update claude md --- CLAUDE.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index c8fec9f..5e8f56a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1533,10 +1533,14 @@ Glide.with(itemView.context).load(glideUrl).into(binding.ivThumbnail) ### 双端验证命令 ```bash -~/Library/Android/sdk/emulator/emulator -list-avds # 可用:Medium_Phone_API_36.1(手机)、Aerologic_Tablet(平板) +~/Library/Android/sdk/emulator/emulator -list-avds # 可用:Aerologic_Phone_5.5_API31(手机,首选)、Aerologic_Tablet(平板)、Medium_Phone_API_36.1 adb -s <设备> shell wm size && adb -s <设备> shell wm density # 确认屏幕参数 -adb -s <设备> logcat -d -s BaseActivity:D # 查看形态识别结果 PHONE(sw=411dp) / TABLET(sw=800dp) +adb -s <设备> logcat -d -s BaseActivity:D # 查看形态识别结果 PHONE(sw=384dp) / TABLET(sw=800dp) adb -s <设备> exec-out screencap -p > /tmp/shot.png # 截图比对 ``` +> 手机端验证**首选 `Aerologic_Phone_5.5_API31`**:按真实交付手持机 1:1 定制——720×1440、5.51 寸(300dpi,sw=384dp)、 +> Android 12 / API 31(与 targetSdk 一致)、arm64-v8a,与实机的差异最小。`Medium_Phone_API_36.1`(1080×2400、API 36) +> 仅作兼容性参考,分辨率与系统版本都和交付机不符。 + > 改动 `BaseActivity` / `BaseBindingActivity` / 公共组件后,**必须在平板上回归**,确认现有平板版行为不变。 From c595a3046b68de54441baf34089150a5a6fb4d22 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 2 Oct 2026 12:09:11 +0800 Subject: [PATCH 14/29] =?UTF-8?q?chore:=20=E5=BC=95=E5=85=A5=20mobile-mcp?= =?UTF-8?q?=20=E9=A1=B9=E7=9B=AE=E7=BA=A7=20MCP=20=E5=B9=B6=E6=B2=89?= =?UTF-8?q?=E6=B7=80=20ADB=C3=97MCP=20=E5=B7=A5=E5=85=B7=E9=80=89=E5=9E=8B?= =?UTF-8?q?=E7=BA=AA=E8=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mobile-mcp 固定 1.0.7 版本;verification.md 新增 2026-10-02 工具选型纪要 (ADB/ui_probe.sh 与 Mobile MCP 的分工规则、实测踩坑、本机环境更新) Co-Authored-By: Claude Code --- .../phone-adapt/references/verification.md | 91 ++++++++++++++++++- .mcp.json | 4 + 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/.claude/skills/phone-adapt/references/verification.md b/.claude/skills/phone-adapt/references/verification.md index 811b0fa..84f417a 100644 --- a/.claude/skills/phone-adapt/references/verification.md +++ b/.claude/skills/phone-adapt/references/verification.md @@ -6,12 +6,12 @@ ## 环境 ```bash -~/Library/Android/sdk/emulator/emulator -list-avds # Medium_Phone_API_36.1(手机) / Aerologic_Tablet(平板) +/opt/homebrew/share/android-commandlinetools/emulator/emulator -list-avds # 本机现仅 AeroLogic_Phone(手机) adb devices -l adb -s shell wm size && adb -s shell wm density ``` -判定形态:手机 1080×2400@420dpi → `PHONE(sw=411dp)`;平板 1280×800@160dpi → `TABLET(sw=800dp)`。 +判定形态:手机 720×1440@292dpi → `PHONE(sw≈394dp)`;平板 1280×800@160dpi → `TABLET(sw=800dp)`(本机平板 AVD 待建,见文末工具选型纪要)。 `ui_probe.sh` 封装了常用操作,比手写 adb 省事且更可靠: @@ -46,7 +46,7 @@ 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 ``` -测试环境账号在记忆文件 `test-env-login.md`(ADMIN / 用户已授权保存),可自主登录。 +测试环境账号在记忆文件 `aerologic-test-account.md`(本机,admin / 用户已授权保存;旧机器文件名为 `test-env-login.md`),可自主登录。 填表用 `input text`,**`#` 不需要转义**——新版 adb 的 input text 参数不经远端 shell 解析, 写 `\#` 反而会把 `\` 也输进去(实测多出一位)。 @@ -179,3 +179,88 @@ adb -s logcat -d -s DBG | grep -A14 "'旧值' -> ''" | grep "at com.luk 本次靠这招定位到 `TextView.onRestoreInstanceState → EditText.setText → doOnTextChanged`, 即复合自定义 View 的 id 串档(见 `components.md`)。**排完删日志。** + +--- + +## 工具选型纪要:ADB(ui_probe.sh) × Mobile MCP 分工(2026-10-02) + +背景:`mobile-mcp`(`@mobilenext/mobile-mcp`)已装入项目级 `.mcp.json`,与本手册的 +ADB/ui_probe.sh 流程并存。以下基于 2026-10-02 在 `AeroLogic_Phone` 模拟器上的实测对比 +(登录流程实测到“填表”一步,因内网不通放弃后续),给出后期开发的工具选择规则。 + +### 能力对照(只列有差异的维度) + +| 维度 | ADB + ui_probe.sh | Mobile MCP | +|------|-------------------|------------| +| 元素定位 | `tap-text` 按文字点,**每次点击前重新 dump**,天然抗布局变化;同名多处可指定序号 | 按 ref 点,键盘弹出/页面导航后 **ref 失效**,必须重新 list(实测踩过) | +| 元素读取 | `texts` 只出可见文字,token 便宜,配 grep 断言(`texts \| grep -c "全选"`) | 完整控件树(text/id/类型/focused/disabled/checked/坐标),信息全但 **token 重**(登录页 54 行) | +| 文本输入 | `input text` + `keycombination`(CTRL+A/DEL 清空——登录 bcrypt 回填坑的标准解法) | `type_keys` 只能输入,**无清空原语**(实测需回落 adb) | +| 请求核对 | `req <关键字>`(OkHttp 多行 pretty JSON 按关键字截取,为本项目定制) | `get_device_logs` 可过滤 tag/进程,多行报文截取不如 `req` 顺手 | +| 崩溃检查 | `crash` | `list_crashes` / `get_crash`(等价) | +| 前台断言 | `dumpsys activity`(手写 grep) | `get_foreground_app` 一次调用 | +| 录屏 | `adb shell screenrecord`(手拉文件) | `start/stop_screen_recording` 直接回传路径,更省事 | +| 批量操作 | 脚本串联,每条一次往返 | `mobile_batch_commands` 一次往返多步(**页面稳定时**才高效) | +| iOS / 云真机 | 无 | 有(本项目 Android-only,暂无用武之地) | +| 依赖 | 零依赖(本机 adb 即可) | npx 每会话冷启动、Node 20+、`@latest` 有版本漂移风险(建议固定 `@1.0.7`) | + +### 选型规则(后期开发按此执行) + +**默认走 ADB + ui_probe.sh**。本手册全部流程不变:构建安装、冷启动/直启、登录、 +wait-text 就绪等待、tap-text 交互、texts 断言、req 抓包、crash 归零、方向采样、Pad 回归、 +样例 Bean 注入。理由:为本项目的坑定制(bcrypt 回填、Loading 吞点击、参数名 A/B)、 +token 成本低、零外部依赖,且 tap-text 每次重新 dump,比 ref 更抗布局变化。 + +**以下四种场景切 Mobile MCP**: + +1. **控件级语义断言**——要看 disabled/checked/focused 状态、控件 id、输入框变换后的值 + (如“密码框 9 个点”“角色 Spinner 是否禁用”“用户名框自动大写成 ADMIN”)。元素树比 + 截图肉眼判读可靠,比 `texts` 信息全。实测:登录页一次拿到 `inputPass text="•••••••••"`、 + 角色 Spinner `disabled`,这类断言 `texts` 做不到(密码框无明文文字) +2. **页面稳定时的多步连续输入**——list 一次拿 ref,`batch_commands` 一次往返完成 + tap→type→tap→type;比逐条 adb 省 round-trip。前提:中间不弹键盘收不起/不导航 + (弹了就见下方回落规则) +3. **录屏取证**——复现“先横屏闪 1 秒”类**时序 bug**,mp4 归档进问题清单,比连拍截图省力 +4. **前台应用/安装卸载等状态核查**——`get_foreground_app`、`install/uninstall/launch_app` + 一步到位,省得记 dumpsys/am 语法 + +**回落规则(两者随时可混用,操作同一设备无状态冲突)**: + +- mobile-mcp ref 失效(键盘弹出/导航后点击落空)→ 重新 `list_elements`,或直接换 + `ui_probe.sh tap-text`(按文字,永远新鲜) +- 需要清空输入框(登录 bcrypt 回填)→ 只能 adb:`input keycombination 113 29` + DEL +- 多行请求/响应体核对 → `req`,不用 mobile-mcp 的日志过滤硬凑 + +### 实测踩坑(Mobile MCP,2026-10-02) + +- ⚠️ **键盘弹出会平移布局**:之前 list 出的 ref/坐标失效。batch 里连续 click+type 会把 + 两段文本打进同一个框(用户名框变成 `ADMINAA123456#`)。规避:每步输入完先 + `KEYCODE_BACK` 收键盘再点下一个目标;或点完先确认焦点再 type +- 无“清空字段”原语;`type_keys` 输入即所得,不会帮你选中文本 +- 元素树 token 开销大,断言优先 `texts | grep`,确实要看状态/id 才上 list_elements + +### 本机环境更新(2026-10-02) + +- SDK 根目录:`/opt/homebrew/share/android-commandlinetools`(brew 安装,emulator 包已装) +- 手机 AVD:`AeroLogic_Phone`——720×1440、5.51 寸 292dpi(sw≈394dp,落手机桶 360~411dp)、 + Android 12 / API 31(与 targetSdk 一致)、arm64 纯 64 位(本项目无 abiFilters,唯一含 + .so 的 fimage.aar 自带 arm64-v8a,兼容)、无边框(`showDeviceFrame=no`) +- ⚠️ **旧文档里的 `Aerologic_Phone_5.5_API31`(300dpi/sw=384dp)、`Medium_Phone_API_36.1`、 + `Aerologic_Tablet` 均为旧机器 AVD,本机不存在**。平板回归前需先建平板 AVD + (1280×800@160dpi,`avdmanager create avd` 后照本文「Pad 端回归」执行) +- 启动:`/opt/homebrew/share/android-commandlinetools/emulator/emulator -avd AeroLogic_Phone` + (Quick Boot 快照已存在,二次启动数秒就绪) +- 模拟器 NAT 出网,**内网服务不可达**(本次登录实测“服务器不通”而放弃)——需要真实接口 + 联调时先确认宿主机网络可达内网;不可达时按上文「无数据时怎么核对 UI」注入样例 Bean +- `.mcp.json` 已加 `mobile-mcp` 条目(npx stdio),**建议把 `@latest` 固定为 `@1.0.7`**; + 该文件 git 跟踪,改动需提交后队友才可用 + +### 推荐配合模式(单页验证的完整动线) + +adb 骨架 + mobile-mcp 点睛,一条龙: + +1. **adb**:构建安装 → 冷启动/直启(`am start`)→ 按登录节填表(含 bcrypt 清空顺序) +2. **ui_probe**:`wait-text` 就绪 → `tap-text` 交互 → `texts | grep` 断言 → `req` 抓包 → `crash` 归零 +3. `texts` 断言不够(要看状态/id/变换值)或要连续多步输入 → **mobile-mcp**: + `list_elements` → `batch_commands`(tap/type) +4. 时序类 bug(闪屏/动画/异步错位)→ **mobile-mcp 录屏**取证,问题清单贴 mp4 + 截图 +5. 全程崩溃检查两家等价(`crash` / `list_crashes`),任选 diff --git a/.mcp.json b/.mcp.json index e5ee220..afb6122 100644 --- a/.mcp.json +++ b/.mcp.json @@ -1,5 +1,9 @@ { "mcpServers": { + "mobile-mcp": { + "command": "npx", + "args": ["-y", "@mobilenext/mobile-mcp@1.0.7"] + }, "api-doc": { "type": "http", "url": "https://www.agentfoxapp.com/mcp/976caff7-5f98-4487-bccf-3aa20c92cf1f", From 0d9406af13ddb5d8cc50b5251f0e6907afc472be Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Wed, 30 Sep 2026 15:44:06 +0800 Subject: [PATCH 15/29] =?UTF-8?q?chore:=20SDK=20=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E7=94=B1=20vfox=20=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E8=87=B3=20mise=20=E5=8E=9F=E7=94=9F=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 mise.toml(java = 17,vendor 由全局 shorthand_vendor 控制) - 删除 vfox 配置 .tool-versions / .vfox.toml - 删除指向旧机器 vfox npx 路径的过时 MCP 定义 .claude/mcp.json - 清理 .gitignore 与 settings.local.json 中的 vfox 残留 Co-Authored-By: Claude Code --- .claude/mcp.json | 11 ----------- .claude/settings.local.json | 9 +-------- .gitignore | 2 -- .tool-versions | 1 - .vfox.toml | 2 -- mise.toml | 2 ++ 6 files changed, 3 insertions(+), 24 deletions(-) delete mode 100644 .claude/mcp.json delete mode 100644 .tool-versions delete mode 100644 .vfox.toml create mode 100644 mise.toml diff --git a/.claude/mcp.json b/.claude/mcp.json deleted file mode 100644 index e5ee220..0000000 --- a/.claude/mcp.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "mcpServers": { - "api-doc": { - "type": "http", - "url": "https://www.agentfoxapp.com/mcp/976caff7-5f98-4487-bccf-3aa20c92cf1f", - "headers": { - "Authorization": "Bearer afk_G_VKmHTdXUi3GjQdg5AeHeH-0BSYQEPP" - } - } - } -} diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 7d4ef25..f1a0421 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -96,8 +96,6 @@ "Read(//Library/Java/JavaVirtualMachines/**)", "Read(//usr/local/**)", "Read(//opt/homebrew/opt/**)", - "Bash(/Users/kid/.vfox/sdks/java/bin/java -version 2>&1)", - "Bash(export JAVA_HOME=/Users/kid/.vfox/sdks/java)", "mcp__apifox__read_project_oas_kcl8s7", "mcp__apifox__refresh_project_oas_kcl8s7", "mcp__apifox__read_project_oas_ref_resources_kcl8s7", @@ -156,10 +154,5 @@ "ask": [] }, "enableAllProjectMcpServers": true, - "enabledMcpjsonServers": [ - "空港集团 - API 文档", - "apifox", - "aerologic-app", - "apidoc" - ] + "enabledMcpjsonServers": [] } diff --git a/.gitignore b/.gitignore index 9c18240..472a120 100644 --- a/.gitignore +++ b/.gitignore @@ -191,8 +191,6 @@ fabric.properties !/gradle/wrapper/gradle-wrapper.jar # End of https://www.toptal.com/developers/gitignore/api/androidstudio,gradle,java,kotlin -.vfox/ -.vfox/sdks/java # Auto Claude data directory .auto-claude/ diff --git a/.tool-versions b/.tool-versions deleted file mode 100644 index 3f33dca..0000000 --- a/.tool-versions +++ /dev/null @@ -1 +0,0 @@ -java 17.0.16+8-amzn diff --git a/.vfox.toml b/.vfox.toml deleted file mode 100644 index f8033e2..0000000 --- a/.vfox.toml +++ /dev/null @@ -1,2 +0,0 @@ -[tools] -java = "17+35-amzn" diff --git a/mise.toml b/mise.toml new file mode 100644 index 0000000..18090eb --- /dev/null +++ b/mise.toml @@ -0,0 +1,2 @@ +[tools] +java = "17" From 18e438550c5afd8fc8606aad05e3447be87b1d4b Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 9 Oct 2026 03:14:04 -0700 Subject: [PATCH 16/29] =?UTF-8?q?chore:=20=E6=9C=AC=E5=9C=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7=E5=90=8C=E6=AD=A5=E7=BA=BF=E4=B8=8A=201.8.7?= =?UTF-8?q?=EF=BC=88versionCode=2087=EF=BC=89=EF=BC=8C=E9=81=BF=E5=85=8D?= =?UTF-8?q?=E8=81=94=E8=B0=83=E6=97=B6=E8=A7=A6=E5=8F=91=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=E5=BC=B9=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c9dfb46..794d215 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,8 +26,8 @@ android { applicationId "com.lukouguoji.aerologic" minSdkVersion 24 targetSdkVersion 30 - versionCode 88 - versionName "1.8.8" + versionCode 87 + versionName "1.8.7" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" From f6b3842882d433f2943e81dc0da770c2a277db72 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 9 Oct 2026 03:14:04 -0700 Subject: [PATCH 17/29] =?UTF-8?q?feat(=E5=87=BA=E6=B8=AF=E7=A7=BB=E5=BA=93?= =?UTF-8?q?):=20=E5=AF=B9=E6=8E=A5=E5=90=8E=E7=AB=AF=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=87=BA=E5=8F=82=20flight/businessName/opUserName=EF=BC=88?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E6=B8=85=E5=8D=95=20#1~#3=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 卡片航班信息绑 flight(航班日期/航班号),不再占位 - 详情页业务类型绑 businessName、移库人绑 opUserName(均回退编码) - 内网实测:已移库运单 opId/opdate/opUserName 均已回填 Co-Authored-By: Claude Opus 5.5 --- .../java/com/lukouguoji/module_base/bean/GjcMove.kt | 11 +++++++++++ .../main/res/layout/activity_int_exp_move_detail.xml | 8 ++++---- module_gjc/src/main/res/layout/item_int_exp_move.xml | 4 ++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMove.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMove.kt index deded4b..81374eb 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMove.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMove.kt @@ -44,6 +44,9 @@ data class GjcMove( var likeNo: String = "", // 部分运单号no(模糊查询) var range: String = "", + var flight: String = "", // 航班信息(航班日期/航班号,如 20260924/MU2222) + var businessName: String = "", // 业务类型名称(中) + var opUserName: String = "", // 操作人(移库人)姓名 // UI扩展字段 - 使用ObservableBoolean实现自动UI更新 val checked: ObservableBoolean = ObservableBoolean(false) @@ -67,6 +70,14 @@ data class GjcMove( val goodsName: String get() = goodsCn.ifEmpty { goods } + /** 业务类型:优先中文名称,为空回退编码 */ + val businessDisplay: String + get() = businessName.ifEmpty { businessType } + + /** 移库人:优先姓名,为空回退操作人ID */ + val opUserDisplay: String + get() = opUserName.ifEmpty { opId } + /** * 详情页字段统一空值占位。 * 接口对 businessType / opdate / opId 等字段常返回 null, diff --git a/module_gjc/src/main/res/layout/activity_int_exp_move_detail.xml b/module_gjc/src/main/res/layout/activity_int_exp_move_detail.xml index 7698a48..9ba56b5 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_move_detail.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_move_detail.xml @@ -7,8 +7,8 @@ · 卡片二:绿色表头「移库信息」+ 移库人 / 移库时间(仅已移库显示) 字段全部由列表项带入,不额外请求接口。 - 接口 IntExpMove/pageQuery 目前对 businessType / opdate / opId 恒返回 null, - 按约定占位 "-"(见 GjcMove.orDash),后端补齐后自动显示。 + 业务类型绑 businessName(中文名称),移库人绑 opUserName(姓名),均回退编码; + 未移库运单 opdate / opId 为空,按约定占位 "-"(见 GjcMove.orDash)。 设计稿里红色标签写的是「国际进港」,但本页属国际出港,判断为设计稿复制粘贴笔误, 实际绑运单类型 awbTypeName(真实值形如「国际出港(国际直航)」)。 @@ -121,7 +121,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.businessType)}" + android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.businessDisplay)}" android:textColor="@color/phone_text_body" android:textSize="14sp" /> @@ -245,7 +245,7 @@ android:layout_height="wrap_content" android:layout_weight="1" title='@{"移库人"}' - value="@{viewModel.dataBean.opId}" /> + value="@{viewModel.dataBean.opUserDisplay}" /> - + From b3b884504d9b2998fcaedc410b79dcbb085d41bf Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 9 Oct 2026 03:14:04 -0700 Subject: [PATCH 18/29] =?UTF-8?q?feat(=E5=87=BA=E5=BA=93=E4=BA=A4=E6=8E=A5?= =?UTF-8?q?):=20=E7=AD=9B=E9=80=89=E5=AF=B9=E9=BD=90=E5=B9=B3=E6=9D=BF?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E5=8F=82=E6=95=B0=EF=BC=8CTab=20=E8=A7=92?= =?UTF-8?q?=E6=A0=87=E6=94=B9=E7=94=A8=20uldNumber=EF=BC=88=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E6=B8=85=E5=8D=95=20#4/#6=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 后端不提供交接人查询入参:手机筛选弹层「交接人」替换为平板同款「目的站」(fdest),移除 hoId 与交接人下拉 - pageQueryTotal 已修复且新增 uldNumber(板箱数),Tab 角标改取 uldNumber - ManifestTotalDto 补齐后端统一统计 DTO 的分项字段(uldNumber/storedNumber/departedNumber/ notClearNumber/clearNumber/waitCheckInNumber/checkingNumber/flightNumber) - 内网实测:无条件 已交接=2(列表 total 同为 2),fdest=PEK 时列表与角标均为 0 Co-Authored-By: Claude Opus 5.5 --- .../module_base/bean/ManifestTotalDto.kt | 12 ++++++++- .../gjc/activity/IntExpOutHandoverActivity.kt | 4 +-- .../viewModel/IntExpOutHandoverViewModel.kt | 27 +++++++------------ .../layout/activity_int_exp_out_handover.xml | 11 ++++---- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/ManifestTotalDto.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/ManifestTotalDto.kt index c54ec76..9df5bcf 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/ManifestTotalDto.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/ManifestTotalDto.kt @@ -8,5 +8,15 @@ data class ManifestTotalDto( var wbNumber: Int = 0, // 运单票数/总票数 var totalPc: Long = 0, // 总件数 var totalWeight: Double = 0.0, // 总重量 - var cargoWeight: Double = 0.0 // 总货重 + var cargoWeight: Double = 0.0, // 总货重 + + // ===== 后端统一统计 DTO 的分项计数(2026-09 后端补齐,按接口各取所需) ===== + var flightNumber: Int = 0, // 航班数 + var uldNumber: Int = 0, // 板箱数(出库交接 Tab 角标) + var storedNumber: Int = 0, // 已入库票数(出港/进港查询) + var departedNumber: Int = 0, // 已离港(出港)/ 已出库(进港)票数 + var notClearNumber: Int = 0, // 未清仓票数(出港/进港仓库) + var clearNumber: Int = 0, // 已清仓票数(出港/进港仓库) + var waitCheckInNumber: Int = 0, // 待计重票数(出港计重) + var checkingNumber: Int = 0 // 计重中票数(出港计重) ) diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverActivity.kt index 243ff95..f38477c 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpOutHandoverActivity.kt @@ -72,12 +72,12 @@ class IntExpOutHandoverActivity : /** * 手机版筛选:重置 * - * 只清空弹层内的三个条件(航班日期 / 航班号 / 交接人),不影响 Tab 与顶部搜索框。 + * 只清空弹层内的三个条件(航班日期 / 航班号 / 目的站),不影响 Tab 与顶部搜索框。 */ fun resetFilter() { viewModel.flightDate.value = "" viewModel.flightNo.value = "" - viewModel.hoId.value = "" + viewModel.fdest.value = "" } /** 手机版筛选:确认 */ diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverViewModel.kt index 40e57ba..c3a6db9 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpOutHandoverViewModel.kt @@ -18,7 +18,6 @@ import com.lukouguoji.module_base.ktx.launchLoadingCollect 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 dev.utils.common.DateUtils import com.lukouguoji.module_base.ktx.formatDate @@ -36,12 +35,8 @@ class IntExpOutHandoverViewModel : BasePageViewModel() { val uldNo = MutableLiveData("") // ULD编号 // ========== 手机版(5.5 寸手持端)专用筛选条件 ========== - // 平板布局不含对应控件,两者保持空值 → 不会进入请求参数,平板查询行为与改造前完全一致 + // 平板布局不含对应控件,保持空值 → 不会进入请求参数,平板查询行为与改造前完全一致 val handoverState = MutableLiveData("") // 交接状态:"" 全部 / "0" 待交接 / "1" 已交接 - val hoId = MutableLiveData("") // 交接人(仓管编码) - - /** 交接人下拉数据(仅手机版筛选弹层使用,由 [initPhoneExtras] 触发加载) */ - val hoUserList = MutableLiveData>(emptyList()) /** 手机版状态 Tab 配置 */ val handoverStateTabs = MutableLiveData( @@ -52,7 +47,7 @@ class IntExpOutHandoverViewModel : BasePageViewModel() { val handoverStateCounts = MutableLiveData(listOf("", "")) /** - * 是否启用手机版专属数据(Tab 角标计数、交接人下拉)。 + * 是否启用手机版专属数据(Tab 角标计数)。 * * 由 Activity 在手机形态下置 true。平板端保持 false, * 因此不会产生任何额外接口请求,平板行为零变化。 @@ -70,15 +65,12 @@ class IntExpOutHandoverViewModel : BasePageViewModel() { val selectedCount = MutableLiveData("0") /** - * 开启手机版专属数据:默认停留「待交接」Tab、加载交接人下拉、启用 Tab 角标计数。 + * 开启手机版专属数据:默认停留「待交接」Tab、启用 Tab 角标计数。 * 仅由手机形态的 Activity 调用。 */ fun initPhoneExtras() { phoneExtrasEnabled = true handoverState.value = "0" - DictUtils.getWHSUserList(addAll = false) { list -> - hoUserList.postValue(list) - } } fun onItemCheckChanged() { @@ -218,11 +210,10 @@ class IntExpOutHandoverViewModel : BasePageViewModel() { "fno" to flightNo.value?.ifEmpty { null }, "fdest" to fdest.value?.ifEmpty { null }, "uld" to uldNo.value?.ifEmpty { null }, - // 以下两项为手机版新增筛选维度,平板端保持空值故不参与查询 + // 手机版 Tab 维度,平板端保持空值故不参与查询 // 参数名以 api-doc 为准:交接状态为 handoverState(integer,0 未交接 / 1 已交接)。 - // hoId(交接人)后端查询入参暂不支持,已记录到 documents/后端接口对接问题清单.xlsx - "handoverState" to handoverState.value?.ifEmpty { null }, - "hoId" to hoId.value?.ifEmpty { null } + // 其余筛选与平板端口径一致(fdate/fno/fdest/uld),后端不提供交接人查询入参 + "handoverState" to handoverState.value?.ifEmpty { null } ) // 列表参数 (含分页) @@ -257,15 +248,15 @@ class IntExpOutHandoverViewModel : BasePageViewModel() { /** * 加载「待交接 / 已交接」Tab 角标数量。 * - * 复用统计接口,分别以 handoverState=0 / 1 各查一次,且沿用当前其余筛选条件, - * 保证角标与列表口径一致。仅手机版调用。 + * 复用统计接口,分别以 handoverState=0 / 1 各查一次,且沿用当前其余筛选条件; + * 角标取 uldNumber(板箱数,与列表 pageQuery 的 total 同口径)。仅手机版调用。 */ private fun loadTabCounts(filterParams: Map) { listOf("0", "1").forEachIndexed { index, state -> val params = (filterParams + mapOf("handoverState" to state)).toRequestBody() launchCollect({ NetApply.api.getIntExpOutHandoverTotal(params) }) { onSuccess = { result -> - val count = (result.data?.wbNumber ?: 0).toString() + val count = (result.data?.uldNumber ?: 0).toString() val current = handoverStateCounts.value?.toMutableList() ?: mutableListOf("", "") if (index < current.size) { diff --git a/module_gjc/src/main/res/layout/activity_int_exp_out_handover.xml b/module_gjc/src/main/res/layout/activity_int_exp_out_handover.xml index 6d781bf..d7590d4 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_out_handover.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_out_handover.xml @@ -145,15 +145,14 @@ type="@{PhoneDataLayoutType.INPUT}" value="@={viewModel.flightNo}" /> - + + hint='@{"请输入目的站"}' + title='@{"目的站"}' + type="@{PhoneDataLayoutType.INPUT}" + value="@={viewModel.fdest}" /> From 415b685a85bf4de383dfe758b220840b3687afc7 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 9 Oct 2026 03:14:04 -0700 Subject: [PATCH 19/29] =?UTF-8?q?feat(ULD=E7=AE=A1=E7=90=86):=20=E5=AF=B9?= =?UTF-8?q?=E6=8E=A5=E5=90=8E=E7=AB=AF=E8=B0=83=E6=95=B4=E2=80=94=E2=80=94?= =?UTF-8?q?=E4=B8=A4=E6=80=81=E7=8A=B6=E6=80=81/=E6=9D=A5=E6=BA=90/inStore?= =?UTF-8?q?Time/=E6=89=B9=E9=87=8F=E5=88=A0=E9=99=A4=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=EF=BC=88=E9=97=AE=E9=A2=98=E6=B8=85=E5=8D=95=20#7~#11=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #7 状态维持两态:移除「占用」预留映射与橙色标签 - #8 来源 source(空运/陆运)出参与保存入参已支持;查询入参不支持 source,筛选弹层移除来源 - #9 查询参数与平板一致(uld/status/uldSuffix):筛选弹层改为 状态 + 所属航司,移除入库时间/进港航班号 - #10 批量删除改为一次调用 /eqm/uld/deleteUldBatch(请求体 ULD 编号数组) - #11 入库时间改绑 inStoreTime;所在港改绑 nowPort(与平板端一致);手机日期行只产出 yyyy-MM-dd, 保存时补齐 00:00:00(仅日期后端返回 400,内网实测) Co-Authored-By: Claude Opus 5.5 --- .../page/uld/edit/UldEditViewModel.kt | 16 ++++--- .../page/uld/list/UldListActivity.kt | 8 ++-- .../page/uld/list/UldListViewModel.kt | 42 +++++-------------- app/src/main/res/layout/activity_uld_edit.xml | 20 ++++----- app/src/main/res/layout/activity_uld_list.xml | 30 +++---------- app/src/main/res/layout/item_uld_list.xml | 11 +++-- .../lukouguoji/module_base/bean/ULDBean.kt | 25 ++++++----- .../lukouguoji/module_base/http/net/Api.kt | 7 ++++ 8 files changed, 63 insertions(+), 96 deletions(-) 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 5a5ae29..76d5c8c 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 @@ -36,7 +36,7 @@ class UldEditViewModel : BaseViewModel() { // ========== 手机版(5.5 寸手持端)专用 ========== - /** 来源选项(本地枚举;后端字段暂不支持,需求已登记 documents/后端接口对接问题清单.xlsx) */ + /** 来源选项(与平板端一致:空运 / 陆运) */ val sourceEditList = MutableLiveData>( listOf( KeyValue("空运", "空运"), @@ -45,8 +45,8 @@ class UldEditViewModel : BaseViewModel() { ) /** - * 手机版状态选项。设计稿为三态(可用/占用/维修),后端枚举当前仅 0/1, - * 按语义映射 可用=0 / 维修=1;「占用」待后端扩展枚举后放开(需求已登记清单)。 + * 手机版状态选项。后端枚举维持两态(0 正常 / 1 故障,不新增「占用」), + * 按设计稿文案映射 可用=0 / 维修=1。 */ val statusPhoneList = listOf( KeyValue("可用", "0"), @@ -64,7 +64,7 @@ class UldEditViewModel : BaseViewModel() { loadCarrierList(null) // 手机版新增默认所在港 HFE(设计稿约定);平板无此预填,行为不变 if (DeviceUtil.isPhone()) { - uldBean.value = uldBean.value?.copy(airport = "HFE") + uldBean.value = uldBean.value?.copy(nowPort = "HFE") } } else { getData() @@ -107,11 +107,15 @@ class UldEditViewModel : BaseViewModel() { showToast("自重不能为空") return } - if (bean.checkInDate.isBlank()) { + if (bean.inStoreTime.isBlank()) { showToast("入库时间不能为空") return } } + // 手机版日期行只产出 yyyy-MM-dd,而 inStoreTime 为 date-time(仅日期后端返回 400),补齐时分秒 + if (DeviceUtil.isPhone() && bean.inStoreTime.length == 10) { + bean.inStoreTime = "${bean.inStoreTime} 00:00:00" + } val isAdd = pageType.value == DetailsPageType.Add launchLoadingCollect({ if (isAdd) NetApply.api.saveUld(bean.toRequestBody()) @@ -121,7 +125,7 @@ class UldEditViewModel : BaseViewModel() { showToast(it.msg.noNull(if (isAdd) "新增成功" else "修改成功")) if (isAdd) { // 清空表单继续录入;手机版保持所在港默认 HFE(与进入页面时一致) - uldBean.value = if (DeviceUtil.isPhone()) ULDBean(airport = "HFE") else ULDBean() + uldBean.value = if (DeviceUtil.isPhone()) ULDBean(nowPort = "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 5d11654..a45b1d8 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 @@ -70,13 +70,11 @@ class UldListActivity : BaseBindingActivity>( + /** 手机版状态下拉:文案与卡片标签一致(可用=0 / 维修=1) */ + val statusPhoneFilterList = MutableLiveData>( listOf( KeyValue("全部", ""), - KeyValue("空运", "空运"), - KeyValue("陆运", "陆运"), + KeyValue("可用", "0"), + KeyValue("维修", "1"), ) ) @@ -82,10 +77,6 @@ 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() ) }) { @@ -122,10 +113,7 @@ class UldListViewModel : BasePageViewModel() { ?.filter { it.checked.get() } ?: emptyList() /** - * 批量删除选中的 ULD。 - * - * 后端仅有单条删除接口(/eqm/uld/deleteUld,批量接口需求已登记清单), - * 此处按队列逐条串行调用,全部完成后统一刷新;中途失败即停并提示。 + * 批量删除选中的 ULD(/eqm/uld/deleteUldBatch,请求体为 ULD 编号数组,一次调用)。 */ fun deleteSelected() { val ulds = getSelectedItems().map { it.uld } @@ -133,19 +121,9 @@ class UldListViewModel : BasePageViewModel() { 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("未知错误")}") + launchLoadingCollect({ NetApply.api.deleteUldBatch(ulds.toRequestBody()) }) { + onSuccess = { + showToast("已删除 ${ulds.size} 条") refresh() } } diff --git a/app/src/main/res/layout/activity_uld_edit.xml b/app/src/main/res/layout/activity_uld_edit.xml index 207934f..ef2af3c 100644 --- a/app/src/main/res/layout/activity_uld_edit.xml +++ b/app/src/main/res/layout/activity_uld_edit.xml @@ -14,8 +14,8 @@ · ULD修改(Modify):编号只读,其余可编辑 + 底部保存 · ULD详情(Details):全只读右对齐 + 顶栏右侧铅笔进入修改 + 额外展示最大装载容积/最大载重 - 「来源」「状态三态(占用)」为后端暂不支持的设计稿要求, - 已登记 documents/后端接口对接问题清单.xlsx,UI 先行、后端补齐后自动生效。 + 字段与平板端一致:来源 source(空运/陆运)、入库时间 inStoreTime、所在港 nowPort; + 状态维持两态(0 可用 / 1 维修,后端不新增「占用」)。 --> @@ -119,11 +119,11 @@ @@ -190,7 +190,7 @@ value="@{viewModel.uldBean.maxWeight}" android:visibility="@{viewModel.pageType == DetailsPageType.Details ? View.VISIBLE : View.GONE}" /> - + - + + value="@={viewModel.uldBean.nowPort}" /> - + - + + value="@={viewModel.uldBean.inStoreTime}" /> - + - - - + hint='@{"请选择状态"}' + list="@{viewModel.statusPhoneFilterList}" + title='@{"状态"}' + type="@{PhoneDataLayoutType.SPINNER}" + value="@={viewModel.status}" /> - - - diff --git a/app/src/main/res/layout/item_uld_list.xml b/app/src/main/res/layout/item_uld_list.xml index 9db6602..e0608c9 100644 --- a/app/src/main/res/layout/item_uld_list.xml +++ b/app/src/main/res/layout/item_uld_list.xml @@ -11,8 +11,7 @@ · 平板独有 id(tv_modify / tv_delete / iv_icon)与手机独有 id(iv_check) 在 Binding 基类中自动为 @Nullable,ViewHolder 判空使用 - 状态标签三色(设计稿):可用=浅绿 / 占用=浅橙 / 维修=浅红。 - 后端当前仅两态(0 可用 / 1 维修),「占用」为后端扩展枚举后的预留,见 ULDBean.statusPhoneName。 + 状态标签:可用=浅绿 / 维修=浅红(后端枚举维持两态 0/1,不含「占用」),见 ULDBean.statusPhoneName。 「来源」字段后端暂无(恒空显示 "-"),已登记 documents/后端接口对接问题清单.xlsx。 --> - + 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 f197b65..1d122c2 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,18 +19,21 @@ data class ULDBean( var status: String = "", // 备注 var remark: String = "", - // ========== 以下字段接口出参已有(api-doc /eqm/uld/pageQuery),此前 Bean 未解析 ========== - // 进港航班号(语义待后端确认,见 documents/后端接口对接问题清单.xlsx) + // ========== 以下字段接口出参已有(api-doc /eqm/uld/pageQuery) ========== + // 进港航班号 var ifNo: String = "", // 出港航班号 var efNo: String = "", - // 入库时间 var checkInDate: String = "", - // 出库时间 var checkOutDate: String = "", - // ========== 后端暂无对应字段,前端按设计稿预留(提交后端忽略,无副作用) ========== - // 来源:空运 / 陆运(后端字段需求已登记清单) + // 来源(空运、陆运) var source: String = "", + // 入库时间 yyyy-MM-dd HH:mm:ss(后端确认「入库时间」取 inStoreTime,与平板端一致) + var inStoreTime: String = "", + // 所在港 + var nowPort: String = "", + // 位置信息 + var nowPosition: String = "", ){ val checked = ObservableBoolean(false) @@ -40,22 +43,18 @@ data class ULDBean( else -> status } - // ========== 手机版(5.5 寸手持端)三态状态展示 ========== - // 设计稿状态为 可用(绿)/占用(橙)/维修(红) 三态;后端当前仅两态(0/1), - // 按语义映射 0→可用、1→维修,"2"→占用为后端扩展枚举后的预留(需求已登记清单)。 + // ========== 手机版(5.5 寸手持端)状态展示 ========== + // 后端确认状态枚举维持两态(0 正常 / 1 故障),不新增「占用」; + // 手机版按设计稿文案映射 0→可用(绿)、1→维修(红)。 /** 手机版状态文案 */ 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/http/net/Api.kt b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt index 00d6ad5..b1226b9 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt @@ -2091,6 +2091,13 @@ interface Api { @POST("eqm/uld/deleteUld") suspend fun deleteUld(@Query("uld") uld: String): BaseResultBean + /** + * 批量删除-ULD-信息(请求体为 ULD 编号字符串数组) + * 接口路径: /eqm/uld/deleteUldBatch + */ + @POST("eqm/uld/deleteUldBatch") + suspend fun deleteUldBatch(@Body data: RequestBody): BaseResultBean + /////////////////////////////////////////////////////////////////////////// // 冷库登记 /////////////////////////////////////////////////////////////////////////// From 40edbe7c67c85e9e6faf848e1890ebfa56828e01 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 9 Oct 2026 03:45:18 -0700 Subject: [PATCH 20/29] =?UTF-8?q?feat(=E5=87=BA=E6=B8=AF=E8=AE=A1=E9=87=8D?= =?UTF-8?q?):=20=E5=AF=B9=E6=8E=A5=E5=90=8E=E7=AB=AF=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E5=88=86=E9=A1=B9/=E8=AE=A1=E9=87=8D=E4=BA=BA/=E9=80=9A?= =?UTF-8?q?=E9=81=93=E5=8F=B7/=E6=89=98=E7=9B=98=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=EF=BC=8C=E7=AD=9B=E9=80=89=E5=AF=B9=E9=BD=90=E5=B9=B3=E6=9D=BF?= =?UTF-8?q?=EF=BC=88=E9=97=AE=E9=A2=98=E6=B8=85=E5=8D=95=20#12~#18?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #12 三格统计改取 pageQueryTotal 出参 waitCheckInNumber/checkingNumber(一次请求), 不再依赖 checkIn 入参过滤(内网实测 pageQuery 的 checkIn 过滤仍被忽略,统计出参正确) - #13 待计重筛选对齐平板:航班日期/代理人/特码(移除通道号/承运人/运单类型) - #14 计重记录筛选对齐平板:航班日期/代理人/特码(移除入库日期起止;dest/opId 实测被忽略一并移除) - #15 运单详情「通道号」绑 checked/pageQuery 出参 passageWay - #16 计重明细/修改记录「计重人」绑 listRecordByWh 出参 opUserName(回退 opId) - #17 arriveFlag 已回填,「已提前运抵」置灰态生效(无需改代码,实机确认) - #18 托盘改用平板同款 trayNumber + trayTotalWeight(= 数量 × 自重,自重默认 18kg); 记录卡片/修改记录托盘自重绑 trayTotalWeight;修复托盘输入框 Double 回写致光标跳位(输 18 存成 81) - 内网实测:三格 6/5/1;分托计重 trayNumber=2/trayTotalWeight=36 落库;修改记录保存 18.0 Co-Authored-By: Claude Opus 5.5 --- .../module_base/bean/GjcCheckInRecord.kt | 30 ++++++++++---- .../lukouguoji/module_base/bean/GjcMaWb.kt | 4 +- .../module_base/bean/GjcWeighingRecordBean.kt | 1 + .../bean/GjcWeighingStatisticsBean.kt | 2 + .../gjc/activity/GjcWeighingListActivity.kt | 5 +-- .../activity/GjcWeighingRecordListActivity.kt | 5 +-- .../GjcWeighingRecordDetailsViewModel.kt | 2 +- .../viewModel/GjcWeighingRecordViewModel.kt | 20 ++-------- .../viewModel/GjcWeighingStartViewModel.kt | 37 +++++++++++------ .../gjc/viewModel/GjcWeighingViewModel.kt | 40 ++++--------------- .../res/layout/activity_gjc_weighing_list.xml | 40 ++++++++----------- .../activity_gjc_weighing_record_details.xml | 9 +++-- .../activity_gjc_weighing_record_list.xml | 35 ++-------------- .../layout/activity_gjc_weighing_start.xml | 12 +++--- .../activity_gjc_weighing_wb_detail.xml | 7 ++-- .../res/layout/item_gjc_check_in_record.xml | 8 ++-- 16 files changed, 105 insertions(+), 152 deletions(-) diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcCheckInRecord.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcCheckInRecord.kt index 41b3456..28b0f86 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcCheckInRecord.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcCheckInRecord.kt @@ -22,9 +22,16 @@ data class GjcCheckInRecord( var weight: Double = 0.0, // 运抵重量 var volume: Double = 0.0, // 运抵体积 var whId: Long = 0, // GJC_WAREHOUSE.ID - var carWeight: String = "" // 托盘自重 + var carWeight: String = "", // 托盘车重(平板托盘车号反查值) + var trayNumber: Int = 0, // 托盘数量 + var trayTotalWeight: Double = 0.0, // 托盘重量(托盘数量 × 托盘自重,与平板端一致) + var opUserName: String = "" // 计重人姓名(opId 关联查询) ) : BaseObservable() { + /** 计重人:优先姓名,为空回退操作员编码 */ + val opUserDisplay: String + get() = opUserName.ifEmpty { opId } + // 数据变化回调 var onDataChanged: (() -> Unit)? = null @@ -54,14 +61,23 @@ data class GjcCheckInRecord( } } - // 托盘自重的字符串表示(用于双向绑定,5.5寸手机版「修改记录」覆层) + /** + * 托盘重量输入原文(手机「修改记录」覆层)。保留原文而非由 Double 反推: + * 输入 "1" 时若 getter 返回 "1.0",输入框会被重设、光标回到开头,再输 "8" 就成了 "81"(实机踩过)。 + * transient:不参与 Gson 提交序列化。 + */ + @Transient + private var trayTotalWeightInput: String? = null + + // 托盘重量的字符串表示(用于双向绑定,5.5寸手机版「修改记录」覆层) @get:Bindable - var carWeightStr: String - get() = carWeight + var trayTotalWeightStr: String + get() = trayTotalWeightInput ?: if (trayTotalWeight == 0.0) "" else trayTotalWeight.toString() set(value) { - if (carWeight != value) { - carWeight = value - notifyPropertyChanged(BR.carWeightStr) + if (trayTotalWeightStr != value) { + trayTotalWeightInput = value + trayTotalWeight = value.toDoubleOrNull() ?: 0.0 + notifyPropertyChanged(BR.trayTotalWeightStr) onDataChanged?.invoke() } } diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt index c99ba2d..d705f06 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcMaWb.kt @@ -76,8 +76,8 @@ data class GjcMaWb( var carNumber: String? = null, // 车牌号 var passageWay: String? = null, // 通道号 var passageWayId: String? = null, - var palletNumber: String? = null, // 托盘数量(5.5寸手机版开始计重页,后端暂无该入参,见接口问题清单) - var carWeight: String? = null, // 托盘自重(5.5寸手机版手输,后端暂无该入参,见接口问题清单) + var trayNumber: Int? = null, // 托盘数量(splitCheckIn / completeCheckIn 入参,与平板端一致) + var trayTotalWeight: Double? = null, // 托盘重量 = 托盘数量 × 托盘自重 // ==================== 状态信息 ==================== var checkIn: String? = null, // 收运状态。0:待收运,1:已收运,2:收运中 diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcWeighingRecordBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcWeighingRecordBean.kt index 87e8625..2c95b45 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcWeighingRecordBean.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcWeighingRecordBean.kt @@ -73,6 +73,7 @@ class GjcWeighingRecordBean : Serializable { var paperTime: String = "" // 单据时间 var userName: String = "" // 收运人 + var passageWay: String = "" // 通道号(计重时选定的通道号名称) var userId: String = "" // 收运人ID var remark: String = "" // 备注 diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcWeighingStatisticsBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcWeighingStatisticsBean.kt index 602f236..92ca382 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcWeighingStatisticsBean.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcWeighingStatisticsBean.kt @@ -10,4 +10,6 @@ class GjcWeighingStatisticsBean { var totalPc: Long = 0 // 总件数 var totalWeight: Double = 0.0 // 总重量 var cargoWeight: Double = 0.0 // 总货重 + var waitCheckInNumber: Int = 0 // 待计重票数(IntExpCheckIn/pageQueryTotal) + var checkingNumber: Int = 0 // 计重中票数(IntExpCheckIn/pageQueryTotal) } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt index b10a91e..e733adb 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt @@ -78,10 +78,9 @@ class GjcWeighingListActivity : /** 手机版筛选:重置(只清弹层内条件,不影响顶部搜索框) */ fun resetFilter() { - viewModel.channelFilter.value = "" - viewModel.carrierFilter.value = "" - viewModel.awbTypeFilter.value = "" + viewModel.flightDate.value = "" viewModel.agentCode.value = "" + viewModel.spCode.value = "" } /** 手机版筛选:确认 */ diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt index 836ed9c..c1352d0 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt @@ -75,12 +75,9 @@ class GjcWeighingRecordListActivity : /** 手机版筛选:重置(只清弹层内条件,不影响顶部搜索框) */ fun resetFilter() { - viewModel.checkInDateStart.value = "" - viewModel.checkInDateEnd.value = "" + viewModel.flightDate.value = "" viewModel.agentCode.value = "" viewModel.spCode.value = "" - viewModel.destFilter.value = "" - viewModel.opUserFilter.value = "" } /** 手机版筛选:确认 */ diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordDetailsViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordDetailsViewModel.kt index 7548180..1f04bb8 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordDetailsViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordDetailsViewModel.kt @@ -145,7 +145,7 @@ class GjcWeighingRecordDetailsViewModel : BaseViewModel() { totalWeight.value = String.format("%.2f", sumWeight) // 计算托盘总重(手机版顶部卡片) - val sumCarWeight = records.sumOf { it.carWeight.toDoubleOrNull() ?: 0.0 } + val sumCarWeight = records.sumOf { it.trayTotalWeight } totalCarWeight.value = String.format("%.2f", sumCarWeight) // 计算重量误差百分比 diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordViewModel.kt index 65a195e..91795c1 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordViewModel.kt @@ -48,28 +48,19 @@ class GjcWeighingRecordViewModel : BasePageViewModel() { // ========== 5.5寸手机版专属字段(平板不调用 initPhoneExtras,行为零变化) ========== - /** 目的站(后端支持入参 dest) */ - val destFilter = MutableLiveData("") - - /** 计重人(后端支持入参 opId,下拉复用仓库用户列表) */ - val opUserFilter = MutableLiveData("") - val whsUserList = MutableLiveData>(emptyList()) - - /** 入库日期起/止(后端暂无对应入参,传 opDateStart/opDateEnd 预留参数,见接口问题清单) */ - val checkInDateStart = MutableLiveData("") - val checkInDateEnd = MutableLiveData("") + // 手机版筛选弹层与平板端查询参数保持一致(后端确认):航班日期 / 代理人 / 特码, + // 运单号走顶部搜索框;dest / opId / 收运时间范围后端均不支持(dest、opId 内网实测被忽略) /** 由手机形态的 Activity 置 true,平板保持 false(不产生任何额外请求与参数) */ private var phoneExtrasEnabled = false /** - * 开启手机版专属数据:放开「今天」默认日期(设计稿筛选无航班日期)、加载计重人下拉。 + * 开启手机版专属数据:放开「今天」默认日期(手机默认查全量,航班日期在筛选弹层可选)。 * 仅由手机形态的 Activity 调用。 */ fun initPhoneExtras() { phoneExtrasEnabled = true flightDate.value = "" - DictUtils.getWHSUserList { whsUserList.postValue(it) } } /////////////////////////////////////////////////////////////////////////// @@ -173,11 +164,6 @@ class GjcWeighingRecordViewModel : BasePageViewModel() { baseParams["wbNo"] = null baseParams["likeNo"] = key } - baseParams["dest"] = destFilter.value?.ifEmpty { null } - baseParams["opId"] = opUserFilter.value?.ifEmpty { null } - // 入库日期起/止为后端预留参数(暂无对应入参,静默忽略,见接口问题清单) - baseParams["opDateStart"] = checkInDateStart.value?.ifEmpty { null } - baseParams["opDateEnd"] = checkInDateEnd.value?.ifEmpty { null } } // 构建查询参数(列表接口) diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingStartViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingStartViewModel.kt index fc45172..2b46419 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingStartViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingStartViewModel.kt @@ -72,17 +72,28 @@ class GjcWeighingStartViewModel : BaseViewModel() { val spCodeList = MutableLiveData>() // 特码列表 val businessTypeList = MutableLiveData>() // 业务类型列表 - // 托盘车自重(平板:托盘车号查询回填只读;手机:手输,见下方 initPhoneExtras) + // 托盘车自重(平板:托盘车号查询回填只读) val carWeight = MutableLiveData("0") // ========== 5.5寸手机版专属(平板不调用 initPhoneExtras,行为零变化) ========== - /** 托盘数量(设计稿字段,后端暂无对应入参,提交时传 palletNumber 预留参数,见接口问题清单) */ - val palletNumber = MutableLiveData("") + // 托盘信息(与平板端一致:托盘重量 trayTotalWeight = 托盘数量 × 托盘自重,自重默认 18kg 可编辑) + /** 托盘数量 → 入参 trayNumber */ + val trayNumber = MutableLiveData("") - /** 手机形态标记:为 true 时提交体额外携带 palletNumber / carWeight(后端静默忽略) */ + /** 单个托盘自重(默认 18kg)→ 与数量相乘得入参 trayTotalWeight */ + val trayWeight = MutableLiveData("18") + + /** 手机形态标记:为 true 时提交体携带 trayNumber / trayTotalWeight(平板保持原托盘车号链路) */ private var phoneMode = false + /** 托盘重量 = 托盘数量 × 托盘自重 */ + private fun getTrayTotalWeight(): Double { + val num = trayNumber.value?.toIntOrNull() ?: 0 + val weight = trayWeight.value?.toDoubleOrNull() ?: 0.0 + return num * weight + } + /** 仅由手机形态的 Activity 调用 */ fun initPhoneExtras() { phoneMode = true @@ -406,10 +417,10 @@ class GjcWeighingStartViewModel : BaseViewModel() { remark = pageRemark.value - // 手机版专属:托盘数量/托盘自重(后端暂无对应入参,静默忽略;平板 phoneMode 恒 false,字段为 null 不进请求体) + // 手机版:托盘数量/托盘重量(平板 phoneMode 恒 false,字段为 null 不进请求体) if (this@GjcWeighingStartViewModel.phoneMode) { - palletNumber = this@GjcWeighingStartViewModel.palletNumber.value?.ifEmpty { null } - carWeight = this@GjcWeighingStartViewModel.carWeight.value?.ifEmpty { null } + trayNumber = this@GjcWeighingStartViewModel.trayNumber.value?.toIntOrNull() + trayTotalWeight = getTrayTotalWeight() } } @@ -442,10 +453,12 @@ class GjcWeighingStartViewModel : BaseViewModel() { maWbBean.value = maWbBean.value?.apply { carId = null remark = null - palletNumber = null + trayNumber = null + trayTotalWeight = null } carWeight.value = "0" - this@GjcWeighingStartViewModel.palletNumber.value = "" + this@GjcWeighingStartViewModel.trayNumber.value = "" + trayWeight.value = "18" } else { showToast(result.msg.noNull("分托计重失败")) } @@ -524,9 +537,9 @@ class GjcWeighingStartViewModel : BaseViewModel() { "checkIn" to "1", // 收运状态设置为已收运 "passageWayId" to channel.value, // 通道号参数 "passageWay" to (channelList.value?.firstOrNull{ it.value == channel.value }?.key ?: ""), - // 手机版专属预留参数(平板 phoneMode 恒 false → null → removeEmptyOrNull 移除,请求体不变) - "palletNumber" to (if (phoneMode) palletNumber.value?.ifEmpty { null } else null), - "carWeight" to (if (phoneMode) carWeight.value?.ifEmpty { null } else null) + // 手机版托盘信息(平板 phoneMode 恒 false → null → removeEmptyOrNull 移除,请求体不变) + "trayNumber" to (if (phoneMode) trayNumber.value?.toIntOrNull() else null), + "trayTotalWeight" to (if (phoneMode) getTrayTotalWeight() else null) ).toRequestBody(removeEmptyOrNull = true) launchLoadingCollect({ diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingViewModel.kt index feabb0f..22b107f 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingViewModel.kt @@ -61,33 +61,23 @@ class GjcWeighingViewModel : BasePageViewModel() { /** 手机版顶部搜索关键字(运单号/航班号混输,getData 内分流:含字母→fno,纯数字→likeNo 模糊) */ val searchKey = MutableLiveData("") - /** 主页三格统计:待计重(checkIn=0)/ 计重中(checkIn=2)数量 */ + /** 主页三格统计:待计重 / 计重中数量(取 pageQueryTotal 出参 waitCheckInNumber / checkingNumber) */ val pendingCount = MutableLiveData("0") val weighingCount = MutableLiveData("0") - /** 手机版筛选弹层字段。通道号/承运人/运单类型后端暂无查询入参(见接口问题清单),传预留参数名 */ - val channelFilter = MutableLiveData("") // 通道号 → passageWayId - val carrierFilter = MutableLiveData("") // 承运人 → by0 - val awbTypeFilter = MutableLiveData("") // 运单类型 → awbType - val channelList = MutableLiveData>(emptyList()) - val awbTypeList = MutableLiveData>(emptyList()) + // 手机版筛选弹层与平板端查询参数保持一致(后端确认):航班日期 / 代理人 / 特码, + // 运单号与航班号走顶部搜索框,均复用上方既有字段 /** 由手机形态的 Activity 置 true,平板保持 false(不产生任何额外请求与参数) */ private var phoneExtrasEnabled = false /** - * 开启手机版专属数据:放开「今天」默认日期(设计稿主页无日期筛选)、加载筛选弹层字典。 + * 开启手机版专属数据:放开「今天」默认日期(设计稿主页默认查全量,日期在筛选弹层可选)。 * 仅由手机形态的 Activity 调用。 */ fun initPhoneExtras() { phoneExtrasEnabled = true flightDate.value = "" - DictUtils.getGjcChannelList { list -> - channelList.postValue(listOf(KeyValue("全部", "")) + list) - } - DictUtils.getWaybillTypeList2(ieFlag = "E", type = "IO") { - awbTypeList.postValue(it) - } } /** @@ -271,10 +261,6 @@ class GjcWeighingViewModel : BasePageViewModel() { else -> baseParams["likeNo"] = key } } - // 以下三个为后端预留参数(暂无对应入参,后端静默忽略,见接口问题清单) - baseParams["passageWayId"] = channelFilter.value?.ifEmpty { null } - baseParams["by0"] = carrierFilter.value?.ifEmpty { null } - baseParams["awbType"] = awbTypeFilter.value?.ifEmpty { null } } // 构建查询参数(列表接口) @@ -304,21 +290,9 @@ class GjcWeighingViewModel : BasePageViewModel() { totalCount.value = (data?.wbNumber ?: 0).toString() totalPc.value = (data?.totalPc ?: 0).toString() totalWeight.value = (data?.totalWeight ?: 0.0).toString() - } - } - - // 手机版三格统计:待计重 / 计重中(各带一次 checkIn 条件的统计请求,仅手机调用) - if (phoneExtrasEnabled) { - listOf("0" to pendingCount, "2" to weighingCount).forEach { (state, liveData) -> - launchCollect({ - NetApply.api.getGjcWeighingStatistics( - (baseParams + mapOf("checkIn" to state)).toRequestBody() - ) - }) { - onSuccess = { result -> - liveData.value = (result.data?.wbNumber ?: 0).toString() - } - } + // 手机版三格统计:后端统计出参直接给出分项计数,无需额外请求 + pendingCount.value = (data?.waitCheckInNumber ?: 0).toString() + weighingCount.value = (data?.checkingNumber ?: 0).toString() } } } diff --git a/module_gjc/src/main/res/layout/activity_gjc_weighing_list.xml b/module_gjc/src/main/res/layout/activity_gjc_weighing_list.xml index f397371..5555aca 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_weighing_list.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_weighing_list.xml @@ -255,34 +255,16 @@ setOnResetClick="@{(v)-> activity.resetFilter()}" title='@{"筛选条件"}'> - - + - + - - - + hint='@{"请选择航班日期"}' + title='@{"航班日期"}' + type="@{PhoneDataLayoutType.DATE}" + value="@={viewModel.flightDate}" /> + + + diff --git a/module_gjc/src/main/res/layout/activity_gjc_weighing_record_details.xml b/module_gjc/src/main/res/layout/activity_gjc_weighing_record_details.xml index b6405b0..68dc0dc 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_weighing_record_details.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_weighing_record_details.xml @@ -6,7 +6,8 @@ 变量 viewModel / activity / editRecord 与平板一致;保留 Activity 中引用的控件 id:recyclerView。 交互差异(业务逻辑全部复用 GjcWeighingRecordDetailsViewModel): - · 顶部卡片:运单号 + 总件数/总重量/托盘总重(totalCarWeight 为手机专属统计字段) + · 顶部卡片:运单号 + 总件数/总重量/托盘总重(totalCarWeight = 各记录 trayTotalWeight 之和,手机专属统计字段) + · 托盘自重绑 trayTotalWeight(与平板端一致,后端 listRecordByWh / updateRecordList 均支持) · 每条记录卡片带「修改」→ 全屏「修改记录」覆层(isEditMode 驱动显隐, 平板端该状态驱动列表内联编辑,互不影响);保存走 onPhoneSaveClick(成功后留在本页) --> @@ -217,15 +218,15 @@ required="@{true}" title='@{"托盘自重(kg)"}' type="@{PhoneFormRowType.INPUT}" - value="@={editRecord.carWeightStr}" /> + value="@={editRecord.trayTotalWeightStr}" /> - + + value="@{editRecord.opUserDisplay}" /> - + - - + value="@={viewModel.flightDate}" /> - - - - - - diff --git a/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml b/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml index c798f17..9e4ae08 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml @@ -9,8 +9,8 @@ 交互差异(业务逻辑全部复用 GjcWeighingStartViewModel): · 手机版从待计重卡片进入(必带 maWbId),故不做运单号输入行 · 平板「地磅称重」输入 → 手机直接编辑「运抵重量」(同一 arriveWeight 字段) - · 平板「托盘车号」→ 手机按设计稿为「托盘数量」(palletNumber 预留字段), - 「托盘自重」相应改为手输(carWeight),两者后端暂无入参,见接口问题清单 + · 平板「托盘车号」→ 手机按设计稿为「托盘数量」+「托盘自重」(默认 18kg), + 提交 trayNumber / trayTotalWeight(= 数量 × 自重),与平板端托盘口径一致 --> @@ -182,7 +182,7 @@ type="@{PhoneFormRowType.TEXT}" value="@{viewModel.arriveVolume}" /> - + + value="@={viewModel.trayNumber}" /> - + + value="@={viewModel.trayWeight}" /> @@ -196,7 +195,7 @@ title='@{"业务类型"}' value="@{viewModel.bean.businessName.empty ? viewModel.bean.businessType : viewModel.bean.businessName}" /> - + + value="@{viewModel.bean.passageWay}" /> diff --git a/module_gjc/src/main/res/layout/item_gjc_check_in_record.xml b/module_gjc/src/main/res/layout/item_gjc_check_in_record.xml index 79ff69a..0e621fc 100644 --- a/module_gjc/src/main/res/layout/item_gjc_check_in_record.xml +++ b/module_gjc/src/main/res/layout/item_gjc_check_in_record.xml @@ -85,7 +85,7 @@ - + - + From b522efa6b9712bea41362ba3706d7aa061ad70fa Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 9 Oct 2026 03:45:27 -0700 Subject: [PATCH 21/29] =?UTF-8?q?feat(=E5=87=BA=E6=B8=AF=E8=BF=90=E6=8A=B5?= =?UTF-8?q?):=20Tab=20=E6=94=B9=E6=9C=8D=E5=8A=A1=E7=AB=AF=20arrivalStatus?= =?UTF-8?q?=20=E8=BF=87=E6=BB=A4=EF=BC=8C=E7=A7=BB=E9=99=A4=E8=A1=A5?= =?UTF-8?q?=E5=85=85=E4=BF=A1=E6=81=AF=E9=A1=B5=EF=BC=88=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E6=B8=85=E5=8D=95=20#19/#20=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #20 待运抵/已运抵 Tab 改为入参 arrivalStatus=0/1 服务端过滤(与平板运抵状态筛选一致), 角标为同条件 pageQueryTotal 全量票数;删除客户端拆分逻辑与 GjcMaWb.isPending (口径变化:申报状态 E 等异常态归入「待运抵」,以后端 arrivalStatus 为准) - #19 后端确认目前无需「补充信息」页:删除 IntExpArriveSupplementActivity/ViewModel/布局与清单注册, 待运抵卡片不再弹长按浮层(已运抵保留 重置/回执) - 筛选移除「代理」:内网实测 IntExpArrive/pageQuery 忽略 agentCode,与平板查询参数对齐 - 内网实测:全量 待运抵 6 / 已运抵 2,与 pageQuery total 一致 Co-Authored-By: Claude Opus 5.5 --- app/src/debug/AndroidManifest.xml | 6 - app/src/main/AndroidManifest.xml | 6 - .../lukouguoji/module_base/bean/GjcMaWb.kt | 7 - .../gjc/activity/IntExpArriveActivity.kt | 17 +- .../IntExpArriveSupplementActivity.kt | 41 ---- .../IntExpArriveSupplementViewModel.kt | 119 ---------- .../gjc/viewModel/IntExpArriveViewModel.kt | 90 ++++--- .../res/layout/activity_int_exp_arrive.xml | 9 - .../activity_int_exp_arrive_supplement.xml | 219 ------------------ .../main/res/layout/item_int_exp_arrive.xml | 13 -- 10 files changed, 46 insertions(+), 481 deletions(-) delete mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSupplementActivity.kt delete mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveSupplementViewModel.kt delete mode 100644 module_gjc/src/main/res/layout/activity_int_exp_arrive_supplement.xml diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml index cfe6128..b382fdf 100644 --- a/app/src/debug/AndroidManifest.xml +++ b/app/src/debug/AndroidManifest.xml @@ -98,12 +98,6 @@ android:exported="true" tools:replace="android:exported" /> - - - - - (bean.haWbList.orEmpty()) - IntExpArriveSupplementActivity.start(this, bean.wbNo.orEmpty(), list) - } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (requestCode) { diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSupplementActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSupplementActivity.kt deleted file mode 100644 index 1d510b2..0000000 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpArriveSupplementActivity.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.lukouguoji.gjc.activity - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import com.lukouguoji.gjc.R -import com.lukouguoji.gjc.databinding.ActivityIntExpArriveSupplementBinding -import com.lukouguoji.gjc.viewModel.IntExpArriveSupplementViewModel -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.bean.GjcHaWb -import com.lukouguoji.module_base.common.Constant - -/** - * 国际出港运抵-补充信息页(5.5寸手机版专属新页,平板端无对应页面) - * - * 参照 Pad 端国际进港「收发货人信息」补充页的批量应用模式:对该运单整个 haWbList 批量应用 - * 同一份收发货人表单。后端暂无保存接口,见 IntExpArriveSupplementViewModel 顶部注释。 - * 对应设计稿 documents/5.5寸手持端设计文件/04_出港运抵/supplement.html。 - */ -class IntExpArriveSupplementActivity : - BaseBindingActivity() { - - override fun layoutId() = R.layout.activity_int_exp_arrive_supplement - override fun viewModelClass() = IntExpArriveSupplementViewModel::class.java - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("补充信息") - binding.viewModel = viewModel - viewModel.initOnCreated(intent) - } - - companion object { - @JvmStatic - fun start(context: Context, wbNo: String, haWbList: ArrayList) { - val starter = Intent(context, IntExpArriveSupplementActivity::class.java) - .putExtra(Constant.Key.CODE, wbNo) - .putExtra(Constant.Key.DATA, haWbList) - context.startActivity(starter) - } - } -} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveSupplementViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveSupplementViewModel.kt deleted file mode 100644 index eff362a..0000000 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveSupplementViewModel.kt +++ /dev/null @@ -1,119 +0,0 @@ -package com.lukouguoji.gjc.viewModel - -import android.content.Intent -import androidx.lifecycle.MutableLiveData -import com.lukouguoji.module_base.base.BaseViewModel -import com.lukouguoji.module_base.bean.GjcHaWb -import com.lukouguoji.module_base.common.Constant -import com.lukouguoji.module_base.http.net.NetApply -import com.lukouguoji.module_base.ktx.launchCollect -import com.lukouguoji.module_base.ktx.launchLoadingCollect -import com.lukouguoji.module_base.ktx.showToast -import com.lukouguoji.module_base.ktx.toRequestBody -import com.lukouguoji.module_base.ktx.verifyNullOrEmpty -import dev.utils.app.info.KeyValue - -/** - * 国际出港运抵-补充信息 ViewModel(5.5寸手机版专属新页) - * - * 参照 Pad 端国际进港 [com.lukouguoji.gjj.viewModel.IntArrSupplementInfoViewModel] 的 - * 「单一表单批量复制到选中列表」模式:对该运单的整个 haWbList 批量应用同一份收发货人信息。 - * - * ⚠️ 后端暂无保存接口,见 [com.lukouguoji.module_base.http.net.Api.supplementArriveHaWb] 注释 - * 与 documents/后端接口对接问题清单.xlsx。 - */ -class IntExpArriveSupplementViewModel : BaseViewModel() { - - // 表单编辑用数据对象(取首个分单填充,让用户看到已有数据) - val dataBean = MutableLiveData(GjcHaWb()) - - // 批量应用的目标分单列表 - private var haWbList: List = emptyList() - - // 国家代码下拉列表 - val countryCodeList = MutableLiveData>(emptyList()) - - // 通讯方式下拉列表 - val comTypeList = MutableLiveData>(emptyList()) - - @Suppress("UNCHECKED_CAST") - fun initOnCreated(intent: Intent) { - val list = intent.getSerializableExtra(Constant.Key.DATA) as? ArrayList - // .copy() 补上被 Java 序列化跳过的 @Transient 字段(checked 等),见分单明细页同款注释 - haWbList = (list ?: emptyList()).map { it.copy() } - dataBean.value = haWbList.firstOrNull()?.copy() ?: GjcHaWb() - - loadCountryCodeList() - loadComTypeList() - } - - private fun loadCountryCodeList() { - launchCollect({ NetApply.api.getCountryCodeList() }) { - onSuccess = { result -> - countryCodeList.value = result.data?.mapNotNull { bean -> - if (bean.code != null && bean.name != null) KeyValue(bean.name, bean.code) else null - } ?: emptyList() - } - } - } - - private fun loadComTypeList() { - launchCollect({ NetApply.api.getCommunicateTypeList() }) { - onSuccess = { result -> - comTypeList.value = result.data?.mapNotNull { bean -> - if (bean.code != null && bean.name != null) KeyValue(bean.name, bean.code) else null - } ?: emptyList() - } - } - } - - fun cancel() { - getTopActivity().finish() - } - - /** - * 保存按钮点击 - 将表单信息复制到该运单的所有分单,批量提交。 - */ - fun save() { - val formBean = dataBean.value ?: return - - if (formBean.consigneeName.verifyNullOrEmpty("收货人名称不能为空")) return - if (formBean.consigneeCountryCode.verifyNullOrEmpty("收货人国家代码不能为空")) return - if (formBean.consigneeComType.verifyNullOrEmpty("收货人通讯方式不能为空")) return - if (formBean.consigneePnum.verifyNullOrEmpty("收货人联系号码不能为空")) return - if (formBean.consignorName.verifyNullOrEmpty("发货人名称不能为空")) return - if (formBean.consignorCountryCode.verifyNullOrEmpty("发货人国家代码不能为空")) return - if (formBean.consignorComType.verifyNullOrEmpty("发货人通讯方式不能为空")) return - if (formBean.consignorPnum.verifyNullOrEmpty("发货人联系号码不能为空")) return - - if (haWbList.isEmpty()) { - showToast("无可保存的分单数据") - return - } - - val updatedList = haWbList.map { haWb -> - haWb.copy( - consigneeName = formBean.consigneeName, - consigneeCountryCode = formBean.consigneeCountryCode, - consigneeComType = formBean.consigneeComType, - consigneePnum = formBean.consigneePnum, - consigneeAddress = formBean.consigneeAddress, - consignorName = formBean.consignorName, - consignorCountryCode = formBean.consignorCountryCode, - consignorComType = formBean.consignorComType, - consignorPnum = formBean.consignorPnum, - consignorAddress = formBean.consignorAddress - ) - } - - launchLoadingCollect({ NetApply.api.supplementArriveHaWb(updatedList.toRequestBody()) }) { - onSuccess = { - showToast("保存成功") - getTopActivity().finish() - } - onFailed = { code, msg -> - showToast("保存失败:$msg(后端接口暂未支持,见接口问题清单)") - } - } - } -} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt index 4f52294..d20f910 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpArriveViewModel.kt @@ -56,7 +56,7 @@ class IntExpArriveViewModel : BasePageViewModel() { // ========== 5.5寸手机版专属(平板布局不引用,零影响) ========== - /** 当前 Tab:"pending"(待运抵) / "shipped"(已运抵)。接口无申报状态查询参数,Tab 由客户端对已加载数据拆分 */ + /** 当前 Tab:"pending"(待运抵) / "shipped"(已运抵)。查询时映射为入参 arrivalStatus=0/1(与平板端运抵状态筛选一致) */ val currentTab = MutableLiveData("pending") /** Tab 配置 */ @@ -64,7 +64,7 @@ class IntExpArriveViewModel : BasePageViewModel() { listOf(KeyValue("待运抵", "pending"), KeyValue("已运抵", "shipped")) ) - /** 两个 Tab 的角标计数(当前已加载数据的客户端统计,非全量,见接口问题清单) */ + /** 两个 Tab 的角标计数(同条件 + arrivalStatus=0/1 各调一次 pageQueryTotal 取 wbNumber,全量口径) */ val arriveTabCounts = MutableLiveData(listOf("0", "0")) /** 手机版空态(当前 Tab 过滤后无数据时显示,对应设计稿 empty-pending) */ @@ -77,61 +77,51 @@ class IntExpArriveViewModel : BasePageViewModel() { /** 手机版已选数量(底部操作条「已选 N 项」) */ val selectedCountPhone = MutableLiveData("0") - /** 手机版筛选弹层「代理」(后端 pageQuery 支持 agentCode 入参,复用既有 agentCode 语义查询) */ - val agentCodePhone = MutableLiveData("") - val agentListPhone = MutableLiveData>(emptyList()) - private var phoneExtrasEnabled = false /** - * 完整已加载列表(跨分页累计,未按 Tab 过滤)。 - * - * ⚠️ RecyclerView/LinearLayoutManager 不会像普通 ViewGroup 那样让 `View.GONE` 的子项 - * 自动塌陷为 0 高度——它仍按子项的测量高度参与滚动区域计算,导致"隐藏"的卡片在列表里 - * 留下一段空白(已实机截图验证)。因此 Tab 切换不能靠给 item 加 visibility 绑定, - * 必须真正地把适配器的数据集替换成过滤后的子集([applyTabFilterPhone])。 - */ - private var allLoadedList: List = emptyList() - - /** - * 开启手机版专属数据:加载「代理」筛选下拉。仅由手机形态的 Activity 调用。 + * 开启手机版专属数据:Tab(arrivalStatus)与角标统计。仅由手机形态的 Activity 调用。 + * 筛选弹层与平板端查询参数一致(航班日期/航班号),agentCode 内网实测被后端忽略,已移除「代理」。 */ fun initPhoneExtras() { phoneExtrasEnabled = true - launchCollect({ NetApply.api.getIntExpAgentList() }) { - onSuccess = { result -> - agentListPhone.postValue( - listOf(KeyValue("全部", "")) + (result.data ?: emptyList()).map { KeyValue(it.name ?: "", it.code ?: "") } - ) - } - } } /** - * 手机版 Tab 切换:将适配器数据集替换为过滤后的子集(不重新请求)。 + * 手机版 Tab 切换:按 arrivalStatus 重新查询(服务端过滤,分页与角标均为全量口径)。 * 由 Activity 在 [com.lukouguoji.module_base.ui.weight.phone.PhoneStatusTab] 的 * 双向绑定写入 currentTab 后调用。 */ fun onTabChangedPhone() { - applyTabFilterPhone() + refresh() } - private fun applyTabFilterPhone() { - val isPendingTab = currentTab.value == "pending" - val filtered = allLoadedList.filter { it.isPending == isPendingTab } - pageModel.rv?.commonAdapter()?.refresh(filtered) - emptyVisiblePhone.value = filtered.isEmpty() + /** 当前 Tab 对应的运抵状态入参:待运抵=0 / 已运抵=1 */ + private fun currentArrivalStatus(): String = + if (currentTab.value == "shipped") "1" else "0" + + /** 列表加载完成后刷新空态文案(服务端已按 Tab 过滤,adapter 即当前 Tab 数据) */ + private fun updateEmptyStatePhone() { + val isPendingTab = currentTab.value != "shipped" + emptyVisiblePhone.value = pageModel.rv?.commonAdapter()?.items.isNullOrEmpty() emptyTextPhone.value = if (isPendingTab) "暂无待运抵的运单" else "暂无已运抵的运单" - updateCheckAllStatusPhone() } /** - * 根据完整已加载列表重新计算 Tab 角标计数(每次数据变化后调用)。 + * 加载 Tab 角标:同条件 + arrivalStatus=0/1 各调一次 pageQueryTotal,取 wbNumber。 */ - private fun updatePhoneTabCounts() { - val pending = allLoadedList.count { it.isPending }.toString() - val shipped = allLoadedList.count { !it.isPending }.toString() - arriveTabCounts.value = listOf(pending, shipped) + private fun loadPhoneTabCounts(filterParams: Map) { + listOf("0", "1").forEachIndexed { index, status -> + launchCollect({ + NetApply.api.getIntExpArriveTotal((filterParams + mapOf("arrivalStatus" to status)).toRequestBody()) + }) { + onSuccess = { result -> + val current = arriveTabCounts.value?.toMutableList() ?: mutableListOf("0", "0") + current[index] = (result.data?.wbNumber ?: 0).toString() + arriveTabCounts.value = current + } + } + } } /** @@ -439,33 +429,30 @@ class IntExpArriveViewModel : BasePageViewModel() { filterParams["wbNo"] = null filterParams["likeNo"] = key } - filterParams["agentCode"] = agentCodePhone.value?.ifEmpty { null } } + // 手机版 Tab 维度(运抵状态),角标需在不含该条件的基础上分别统计 + val tabParams = if (phoneExtrasEnabled) { + filterParams + mapOf("arrivalStatus" to currentArrivalStatus()) + } else filterParams + // 列表参数 (含分页) - val listParams = (filterParams + mapOf( + val listParams = (tabParams + mapOf( "pageNum" to pageModel.page, "pageSize" to pageModel.limit )).toRequestBody() // 统计参数 (无分页) - val totalParams = filterParams.toRequestBody() + val totalParams = tabParams.toRequestBody() // 获取列表 (带Loading) launchLoadingCollect({ NetApply.api.getIntExpArriveList(listParams) }) { onSuccess = { result -> - // 手机版:自行维护完整累计列表(不依赖 adapter.items 的历史状态,见 allLoadedList 注释) - if (phoneExtrasEnabled) { - val newPageItems = result.list ?: emptyList() - allLoadedList = if (pageModel.page <= 1) newPageItems else allLoadedList + newPageItems - } - pageModel.handleListBean(result) { updateCheckAllStatus() if (phoneExtrasEnabled) { - // 用完整列表强制覆盖 adapter 数据集为当前 Tab 的过滤子集 - applyTabFilterPhone() - updatePhoneTabCounts() + updateEmptyStatePhone() + updateCheckAllStatusPhone() } } // 数据加载完成后,重置全局展开状态为收起 @@ -482,5 +469,10 @@ class IntExpArriveViewModel : BasePageViewModel() { totalWeight.value = (data?.totalWeight ?: 0.0).toString() } } + + // 手机版 Tab 角标(平板不触发) + if (phoneExtrasEnabled) { + loadPhoneTabCounts(filterParams) + } } } diff --git a/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml b/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml index c59a272..0e389bb 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_arrive.xml @@ -177,15 +177,6 @@ type="@{com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayoutType.INPUT}" value="@={viewModel.flightNo}" /> - - diff --git a/module_gjc/src/main/res/layout/activity_int_exp_arrive_supplement.xml b/module_gjc/src/main/res/layout/activity_int_exp_arrive_supplement.xml deleted file mode 100644 index 32bc29e..0000000 --- a/module_gjc/src/main/res/layout/activity_int_exp_arrive_supplement.xml +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/module_gjc/src/main/res/layout/item_int_exp_arrive.xml b/module_gjc/src/main/res/layout/item_int_exp_arrive.xml index af4e1f8..620404a 100644 --- a/module_gjc/src/main/res/layout/item_int_exp_arrive.xml +++ b/module_gjc/src/main/res/layout/item_int_exp_arrive.xml @@ -217,19 +217,6 @@ android:gravity="center" android:orientation="horizontal"> - - - Date: Fri, 9 Oct 2026 03:47:41 -0700 Subject: [PATCH 22/29] =?UTF-8?q?feat(=E5=87=BA=E6=B8=AF=E4=BB=93=E5=BA=93?= =?UTF-8?q?):=20=E7=AD=9B=E9=80=89=E5=AF=B9=E9=BD=90=E5=B9=B3=E6=9D=BF?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E5=8F=82=E6=95=B0=EF=BC=8C=E4=B8=89=E6=A0=BC?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E6=94=B9=E5=8F=96=20notClearNumber/clearNumb?= =?UTF-8?q?er=EF=BC=88=E9=97=AE=E9=A2=98=E6=B8=85=E5=8D=95=20#23/#24?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #23 后端不新增入参:筛选弹层改为平板同款 航班日期/航班号/库位/清仓结果, 移除代理/特码/目的站/运单类型/业务类型/品名(内网实测 agentCode/spCode/dest/awbType/goodsCn 均被忽略) - #24 未清仓/已清仓直接取 pageQueryTotal 出参 notClearNumber/clearNumber, 手机端统计请求由 3 次降为 1 次(与平板相同) - 内网实测:全量 7/7/0;fno=MU2222 时 3/3/0 且列表同步过滤 Co-Authored-By: Claude Opus 5.5 --- .../viewModel/IntExpStorageUseViewModel.kt | 76 +++---------------- .../layout/activity_int_exp_storage_use.xml | 63 +++------------ 2 files changed, 23 insertions(+), 116 deletions(-) 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 152dc19..b076d1f 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,7 +17,6 @@ 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 @@ -43,28 +42,11 @@ class IntExpStorageUseViewModel : BasePageViewModel() { // 筛选弹层显隐 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("") // 品名(中)(同上预留) + // 筛选弹层与平板端查询参数保持一致(后端确认):航班日期 / 航班号 / 库位 / 清仓结果,运单号走顶部搜索框。 + // 代理/特码/目的站/运单类型/业务类型/品名 后端均不支持(内网实测 agentCode/spCode/dest 亦被忽略),已移除 - // 筛选下拉字典(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)。 + // 三格统计:未清仓 / 已清仓(总票数复用 totalWbNumber),直接取 pageQueryTotal 出参 + // notClearNumber / clearNumber(与总票数同一次请求、同条件) val unclearedCount = MutableLiveData("0") val clearedCount = MutableLiveData("0") @@ -76,22 +58,6 @@ class IntExpStorageUseViewModel : BasePageViewModel() { */ 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) - } } /** 筛选按钮点击 - 打开筛选面板 */ @@ -108,12 +74,8 @@ class IntExpStorageUseViewModel : BasePageViewModel() { fun resetFilter() { flightDate.value = "" flightNo.value = "" - agentId.value = "" - spCode.value = "" - dest.value = "" - awbType.value = "" - businessType.value = "" - goodsCn.value = "" + location.value = "" + clearResult.value = "" } /** 确认筛选 - 关闭面板并刷新 */ @@ -385,20 +347,13 @@ 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 }, - "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 } + "clearNormal" to clearResult.value?.ifEmpty { null } ) // 列表参数 (含分页) @@ -428,18 +383,9 @@ class IntExpStorageUseViewModel : BasePageViewModel() { totalWbNumber.value = (data?.wbNumber ?: 0).toString() totalPc.value = (data?.totalPc ?: 0).toString() 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() } + // 手机三格统计分项(平板布局不绑定,无影响) + unclearedCount.value = (data?.notClearNumber ?: 0).toString() + clearedCount.value = (data?.clearNumber ?: 0).toString() } } } 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 1dd552d..f495932 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 @@ -11,8 +11,8 @@ · 平板独有的 checkIcon(底部全选)手机版不提供,Binding 基类中自动变 @Nullable 交互差异(均复用既有 IntExpStorageUseViewModel 字段与接口): - · 平板 5 个横排搜索条 → 手机顶部搜索框(运单号)+ 底部筛选弹层 8 项 - (设计稿弹层无「库位号/清仓结果」两项,对应平板字段保持空值不参与请求) + · 平板 5 个横排搜索条 → 手机顶部搜索框(运单号)+ 底部筛选弹层 4 项 + (航班日期/航班号/库位/清仓结果,后端确认与平板端查询参数保持一致) · 三格统计(总票数/未清仓/已清仓),后两格为手机专属统计请求(initPhoneExtras 开启, 复用 pageQueryTotal 按 clearNormal=0/1 各查一次) · 平板底部批量操作条 → 手机卡片级操作按钮(见 item 布局),无全选/批量 @@ -233,7 +233,7 @@ - + - + - - - - - - + value="@={viewModel.location}" /> - + - - - - - - + value="@={viewModel.clearResult}" /> From d2340d46fb3d265baff37aeada4e1a90b93e9d8e Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 9 Oct 2026 07:31:04 -0700 Subject: [PATCH 23/29] =?UTF-8?q?feat(=E5=87=BA=E6=B8=AF=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?):=20=E4=B8=89=E6=A0=BC=E7=BB=9F=E8=AE=A1=E5=8F=96=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E7=AB=AF=E5=88=86=E9=A1=B9=EF=BC=8C=E7=AD=9B=E9=80=89?= =?UTF-8?q?=E8=A1=A5=E6=97=A5=E6=9C=9F=E7=B1=BB=E5=9E=8B=EF=BC=8C=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E7=A7=BB=E9=99=A4=E9=94=81=E5=AE=9A=E7=8A=B6=E6=80=81?= =?UTF-8?q?/=E8=AE=A1=E8=B4=B9=E9=87=8D=E9=87=8F=EF=BC=88=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E6=B8=85=E5=8D=95=20#21/#22=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #21 已入库/已离港改取 pageQueryTotal 出参 storedNumber/departedNumber(全量口径),删除客户端计数 - #21「起始时间参数无意义」:内网实测 beginDate/endDate 仅在携带 dateState 时生效, 手机筛选新增「日期类型」(入库/离港,默认入库,与主干平板一致),有起止日期时才携带 dateState - #22 后端确认无需展示:运单信息移除「锁定状态」「计费重量」,件重区改两列对齐 - 内网实测:当日入库 2/2/0;切换离港 0/0/0,与直调一致 Co-Authored-By: Claude Opus 5.5 --- .../gjc/viewModel/GjcQueryViewModel.kt | 39 ++++++++----------- .../main/res/layout/activity_gjc_query.xml | 22 ++++++++--- .../res/layout/fragment_gjc_query_waybill.xml | 33 +++++----------- 3 files changed, 41 insertions(+), 53 deletions(-) diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryViewModel.kt index d5c112b..9d1d89a 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcQueryViewModel.kt @@ -7,7 +7,6 @@ import androidx.lifecycle.MutableLiveData import com.lukouguoji.gjc.R import com.lukouguoji.gjc.holder.GjcQueryViewHolder import com.lukouguoji.module_base.base.BasePageViewModel -import com.lukouguoji.module_base.bean.GjcMaWb import com.lukouguoji.module_base.common.Constant import com.lukouguoji.module_base.http.net.NetApply import com.lukouguoji.module_base.ktx.launchCollect @@ -81,14 +80,17 @@ class GjcQueryViewModel : BasePageViewModel() { // 特码下拉列表(设计稿筛选弹层为下拉;平板筛选为文本输入,不加载) val specialCodeList = MutableLiveData>(emptyList()) - // 三格统计:已入库 / 已离港(总票数复用 totalCount,为服务端全量口径) - // 后端无分项统计出参,且文档定义的 isFclose 入参实测被 pageQuery/pageQueryTotal 静默忽略 - // (2026-07-31 内网 A/B 验证,见接口问题清单)——已入库/已离港暂为「已加载数据」客户端计数口径 + // 三格统计:总票数 / 已入库 / 已离港,均取 pageQueryTotal 出参(wbNumber / storedNumber / departedNumber), + // 与列表同条件、服务端全量口径 val storedCount = MutableLiveData("0") val departedCount = MutableLiveData("0") + // 日期类型(0:入库,1:离港),与主干平板端一致。后端 beginDate/endDate 仅在携带 dateState 时生效 + // (内网实测:不带 dateState 时起止日期被忽略)。平板布局(本分支)不绑定,phoneExtras 关闭时不进请求 + val dateState = MutableLiveData("0") + val dateStateList = MutableLiveData(listOf(KeyValue("入库", "0"), KeyValue("离港", "1"))) + private var phoneExtrasEnabled = false - private var phoneLoadedList: List = emptyList() /** * 手机形态专属初始化(Activity 在 DeviceUtil.isPhone() 时调用)。 @@ -186,10 +188,15 @@ class GjcQueryViewModel : BasePageViewModel() { * 核心方法:调用API获取数据并转换PageInfo为BaseListBean */ override fun getData() { + // 手机版:日期类型,仅在有起止日期时携带(平板 phoneExtrasEnabled 恒 false → null 不进请求) + val hasDate = !flightDateStart.value.isNullOrEmpty() || !flightDateEnd.value.isNullOrEmpty() + val dateStateParam = if (phoneExtrasEnabled && hasDate) dateState.value?.toIntOrNull() else null + // 构建查询参数(列表接口) val listParams = mapOf( "pageNum" to pageModel.page, "pageSize" to pageModel.limit, + "dateState" to dateStateParam, "beginDate" to flightDateStart.value!!.ifEmpty { null }, "endDate" to flightDateEnd.value!!.ifEmpty { null }, "agentCode" to agentId.value!!.ifEmpty { null }, @@ -206,6 +213,7 @@ class GjcQueryViewModel : BasePageViewModel() { // 构建查询参数(统计接口 - 使用相同的搜索条件) val totalParams = mapOf( + "dateState" to dateStateParam, "beginDate" to flightDateStart.value!!.ifEmpty { null }, "endDate" to flightDateEnd.value!!.ifEmpty { null }, "agentCode" to agentId.value!!.ifEmpty { null }, @@ -227,14 +235,6 @@ class GjcQueryViewModel : BasePageViewModel() { onSuccess = { pageInfo -> // ⚠️ 核心:使用toBaseListBean()转换PageInfo为BaseListBean pageModel.handleListBean(pageInfo.toBaseListBean()) - - // 手机三格统计:对已加载数据做客户端计数(平板不触发) - if (phoneExtrasEnabled) { - val pageItems = pageInfo.list ?: emptyList() - phoneLoadedList = - if (pageModel.page <= 1) pageItems else phoneLoadedList + pageItems - updatePhoneCounts() - } } } @@ -247,20 +247,13 @@ class GjcQueryViewModel : BasePageViewModel() { totalCount.value = (data?.wbNumber ?: 0).toString() totalPc.value = (data?.totalPc ?: 0).toString() totalWeight.value = (data?.totalWeight ?: 0.0).toString() + // 手机三格统计分项(平板布局不绑定,无影响) + storedCount.value = (data?.storedNumber ?: 0).toString() + departedCount.value = (data?.departedNumber ?: 0).toString() } } } - /** - * 手机三格统计(已入库/已离港):与卡片状态标签同一判定口径(fclose / opDate), - * 统计范围为已加载的列表数据。 - */ - private fun updatePhoneCounts() { - departedCount.value = phoneLoadedList.count { it.isQueryDeparted }.toString() - storedCount.value = - phoneLoadedList.count { !it.isQueryDeparted && it.isQueryStored }.toString() - } - /** * 处理扫码结果 */ diff --git a/module_gjc/src/main/res/layout/activity_gjc_query.xml b/module_gjc/src/main/res/layout/activity_gjc_query.xml index e1aefee..9dff0c7 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_query.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_query.xml @@ -239,21 +239,31 @@ setOnResetClick="@{(v)-> viewModel.resetFilter()}" title='@{"筛选条件"}'> - + + + + - + diff --git a/module_gjc/src/main/res/layout/fragment_gjc_query_waybill.xml b/module_gjc/src/main/res/layout/fragment_gjc_query_waybill.xml index 1c106f1..4bc2c81 100644 --- a/module_gjc/src/main/res/layout/fragment_gjc_query_waybill.xml +++ b/module_gjc/src/main/res/layout/fragment_gjc_query_waybill.xml @@ -11,8 +11,8 @@ 数据全部来自既有 viewModel.maWbData(IntExpSearch/detail 的 maWb+maWbM 合并 Map), 取值统一走 viewModel.str()/dec() 帮助方法(空值兜底 "-")。 - 按设计稿新增展示的字段(承运人/始发站/中转站/目的站/UN编号/锁定状态/计费重量), - 其中锁定状态(lockStatus)与计费重量(cashWeight)在接口文档中无定义,实机核对后如缺失记入问题清单。 + 按设计稿新增展示的字段(承运人/始发站/中转站/目的站/UN编号); + 锁定状态与计费重量后端确认无需展示,已移除(问题清单 #22)。 入库件数/入库重量为 warehouseList 各批次求和(viewModel.inPcTotal/inWeightTotal)。 --> @@ -167,20 +167,13 @@ - + - - + + @@ -286,7 +284,7 @@ android:layout_marginBottom="12dp" android:background="@color/phone_divider" /> - + - - @@ -336,12 +327,6 @@ title='@{"入库重量"}' value="@{viewModel.inWeightTotal}" /> - - - From 1229ecc9201b0d0c6a6dee6c379b28df263b22a7 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 9 Oct 2026 07:32:47 -0700 Subject: [PATCH 24/29] =?UTF-8?q?feat(=E8=BF=9B=E6=B8=AF=E4=BB=93=E5=BA=93?= =?UTF-8?q?):=20=E7=AD=9B=E9=80=89=E5=AF=B9=E9=BD=90=E5=B9=B3=E6=9D=BF?= =?UTF-8?q?=E3=80=81=E7=BB=9F=E8=AE=A1=E5=8F=96=20notClearNumber/clearNumb?= =?UTF-8?q?er=E3=80=81=E8=AF=A6=E6=83=85=E6=8C=89=E5=B9=B3=E6=9D=BF?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=EF=BC=88=E9=97=AE=E9=A2=98=E6=B8=85=E5=8D=95?= =?UTF-8?q?=20#25~#27=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #25 后端不新增入参:筛选弹层改为平板同款 航班日期/航班号/库位/清仓结果, 移除始发站/代理/特码/运单类型/业务类型/品名 - #26 未清仓/已清仓取 pageQueryTotal 出参 notClearNumber/clearNumber,统计请求 3 次 → 1 次 - #27 进港详情按平板:航程 range 替代 始发站/中转站/目的站(无经停站),入库时间(opDate 恒空) 改为平板同款 出库时间 dlvTime - 内网实测:48/42/5;详情 航程 LAX-HFE / UN编号 / 锁定状态 正常显示 - 注意:IntImpStorage/pageQuery 当前对所有过滤条件(含平板自用的 wbNo/fno/fdate/location/clearNormal) 均不生效,属后端缺陷,已登记问题清单 Co-Authored-By: Claude Opus 5.5 --- .../viewModel/IntImpStorageUseViewModel.kt | 70 +++---------------- .../layout/activity_int_imp_storage_use.xml | 61 +++------------- .../layout/fragment_int_imp_query_waybill.xml | 39 +++-------- 3 files changed, 29 insertions(+), 141 deletions(-) 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 5f8e803..e3ab16e 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,7 +18,6 @@ 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 @@ -47,27 +46,10 @@ class IntImpStorageUseViewModel : BasePageViewModel() { // 筛选弹层显隐 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("") // 品名(中)(预留) + // 筛选弹层与平板端查询参数保持一致(后端确认):航班日期 / 航班号 / 库位 / 清仓结果,运单号/航班号走顶部搜索框。 + // 始发站/代理/特码/运单类型/业务类型/品名 后端不支持(内网实测 fdep/agentCode 被忽略),已移除 - // 筛选下拉字典(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 各查一次) + // 三格统计:未清仓 / 已清仓,直接取 pageQueryTotal 出参 notClearNumber / clearNumber val unclearedCount = MutableLiveData("0") val clearedCount = MutableLiveData("0") @@ -79,18 +61,6 @@ class IntImpStorageUseViewModel : BasePageViewModel() { */ 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) - } } /** @@ -129,12 +99,8 @@ class IntImpStorageUseViewModel : BasePageViewModel() { fun resetFilter() { flightDate.value = "" flightNo.value = "" - fdep.value = "" - agentId.value = "" - spCode.value = "" - awbType.value = "" - businessType.value = "" - goodsCn.value = "" + location.value = "" + clearResult.value = "" } /** 确认筛选 - 关闭面板并刷新 */ @@ -354,20 +320,13 @@ 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 }, - "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 } + "clearNormal" to clearResult.value?.ifEmpty { null } ) val listParams = (filterParams + mapOf( @@ -391,18 +350,9 @@ class IntImpStorageUseViewModel : BasePageViewModel() { totalWbNumber.value = (data?.wbNumber ?: 0).toString() totalPc.value = (data?.totalPc ?: 0).toString() 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() } + // 手机三格统计分项(平板布局不绑定,无影响) + unclearedCount.value = (data?.notClearNumber ?: 0).toString() + clearedCount.value = (data?.clearNumber ?: 0).toString() } } } diff --git a/module_gjj/src/main/res/layout/activity_int_imp_storage_use.xml b/module_gjj/src/main/res/layout/activity_int_imp_storage_use.xml index b9df685..12432a5 100644 --- a/module_gjj/src/main/res/layout/activity_int_imp_storage_use.xml +++ b/module_gjj/src/main/res/layout/activity_int_imp_storage_use.xml @@ -11,7 +11,7 @@ · 平板独有的 checkIcon(底部全选)手机版不提供,Binding 基类中自动变 @Nullable 交互差异(均复用既有 IntExpStorageUseViewModel 字段与接口): - · 平板 5 个横排搜索条 → 手机顶部搜索框(运单号)+ 底部筛选弹层 8 项 + · 平板 5 个横排搜索条 → 手机顶部搜索框(运单号)+ 底部筛选弹层 4 项(航班日期/航班号/库位/清仓结果,与平板查询参数一致) (设计稿弹层无「库位号/清仓结果」两项,对应平板字段保持空值不参与请求) · 三格统计(总票数/未清仓/已清仓),后两格为手机专属统计请求(initPhoneExtras 开启, 复用 pageQueryTotal 按 clearNormal=0/1 各查一次) @@ -235,7 +235,7 @@ - + - + - - - - - - + value="@={viewModel.location}" /> - + - - - - - - + value="@={viewModel.clearResult}" /> 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 0bd2ca5..626e03a 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 @@ -12,8 +12,8 @@ 数据全部来自既有 viewModel.maWbData(IntImpSearch/detail 的 maWb Map), 取值统一走 viewModel.str()/dec() 帮助方法(空值兜底 "-")。 字段 key 以平板变体既有绑定为准(awbPc/awbWeight/cashWeight/inPc/inWeight/lockStateText/ - mftStatus/tallyStatus/command);始发站/中转站/目的站/UN编号/入库时间为设计稿新增展示, - key(dep/dest1/dest/unNumber/opDate)按出港同名字段推断,实机核对后如缺失记入问题清单。 + mftStatus/tallyStatus/command);后端确认按平板端展示(问题清单 #27): + 航程 range(无经停站,替代始发站/中转站/目的站)、UN编号 unNumber、出库时间 dlvTime。 --> @@ -121,7 +121,7 @@ - + - - - - - - - - - + title='@{"航程"}' + value='@{viewModel.str(viewModel.maWbData, "range")}' /> - + + title='@{"出库时间"}' + value='@{viewModel.str(viewModel.maWbData, "dlvTime")}' /> From cca62aae29d0b9ab86a4c76f8c174dd18f2389bd Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 9 Oct 2026 07:33:27 -0700 Subject: [PATCH 25/29] =?UTF-8?q?feat(=E6=8F=90=E5=8F=96=E5=87=BA=E5=BA=93?= =?UTF-8?q?):=20=E7=AD=9B=E9=80=89=E5=AF=B9=E9=BD=90=E5=B9=B3=E6=9D=BF?= =?UTF-8?q?=E5=8F=82=E6=95=B0=EF=BC=8C=E5=87=BA=E5=BA=93=E4=BA=BA=E6=94=B9?= =?UTF-8?q?=E7=BB=91=20refUserName=EF=BC=8C=E7=A7=BB=E9=99=A4=E6=97=A0?= =?UTF-8?q?=E5=87=BA=E5=8F=82=E5=8D=A0=E4=BD=8D=EF=BC=88=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E6=B8=85=E5=8D=95=20#28/#29=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #28 后端不新增入参/出参:筛选弹层改为平板同款 缴费日期起止(beginDate/endDate)/代理人/特码, 移除航班日期/航班号;卡片移除「提货车辆」,详情移除「目的港」「业务类型」占位 - 运单号入参 no → wbNo(与主干平板端修复一致,no 为 8 位编号) - #29 Tab 继续按 outState 过滤(后端确认生效);「出库人」改绑新增出参 refUserName(dlvName 是提货人) - 内网:请求体已确认携带 wbNo/outState;测试环境该接口暂无数据(total=0),卡片展示待有数据后复核 Co-Authored-By: Claude Opus 5.5 --- .../module_base/bean/IntImpPickUpDLVBean.kt | 1 + .../gjj/viewModel/IntImpPickUpDLVViewModel.kt | 18 ++++------ .../activity_int_imp_pick_up_detail.xml | 36 +++++-------------- .../layout/activity_int_imp_pick_up_dlv.xml | 17 +++++---- .../res/layout/item_int_imp_pick_up_dlv.xml | 28 ++------------- 5 files changed, 27 insertions(+), 73 deletions(-) diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpPickUpDLVBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpPickUpDLVBean.kt index 7fcef6a..ed780c3 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpPickUpDLVBean.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpPickUpDLVBean.kt @@ -46,6 +46,7 @@ class IntImpPickUpDLVBean : Serializable { var dlvId: String = "" var dlvIdType: String = "" var dlvName: String = "" + var refUserName: String = "" // 出库人姓名(refId 关联查询) var dlvPhone: String = "" var locFlag: String = "" var origin: String = "" diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpPickUpDLVViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpPickUpDLVViewModel.kt index ef4d5b4..e6b87ca 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpPickUpDLVViewModel.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpPickUpDLVViewModel.kt @@ -70,9 +70,7 @@ class IntImpPickUpDLVViewModel : BasePageViewModel() { // 筛选弹层显隐 val filterVisible = MutableLiveData(false) - // 筛选条件(flightDate 为 pageQuery 未定义入参 fdate,预留传参,见接口问题清单) - val flightDate = MutableLiveData("") - val flightNo = MutableLiveData("") + // 筛选弹层与平板端查询参数保持一致(后端确认):缴费日期起止 / 代理人 / 特码,运单号走顶部搜索框 // 特码下拉字典(initPhoneExtras 加载,平板为扫码输入不加载) val specialCodeList = MutableLiveData>(emptyList()) @@ -107,8 +105,8 @@ class IntImpPickUpDLVViewModel : BasePageViewModel() { /** 重置筛选条件 */ fun resetFilter() { - flightDate.value = "" - flightNo.value = "" + paymentDateStart.value = "" + paymentDateEnd.value = "" agentCode.value = "" spCode.value = "" } @@ -204,17 +202,15 @@ class IntImpPickUpDLVViewModel : BasePageViewModel() { * 获取列表数据 */ override fun getData() { - // 手机专属 3 项平板恒为空,不进请求;fdate 为 pageQuery 未定义入参 - //(后端静默忽略,补齐后自动生效,见接口问题清单) + // 查询条件与平板端一致;outState 为手机 Tab 维度(平板恒空不进请求)。 + // 运单号入参用 wbNo(no 为 8 位编号,与主干平板端修复一致) val filterParams = mapOf( "beginDate" to paymentDateStart.value?.ifEmpty { null }, "endDate" to paymentDateEnd.value?.ifEmpty { null }, "agentCode" to agentCode.value?.ifEmpty { null }, - "no" to wbNo.value?.ifEmpty { null }, + "wbNo" to wbNo.value?.ifEmpty { null }, "spCode" to spCode.value?.ifEmpty { null }, - "outState" to outState.value?.ifEmpty { null }, - "fno" to flightNo.value?.ifEmpty { null }, - "fdate" to flightDate.value?.ifEmpty { null } + "outState" to outState.value?.ifEmpty { null } ) val listParams = (filterParams + mapOf( diff --git a/module_gjj/src/main/res/layout/activity_int_imp_pick_up_detail.xml b/module_gjj/src/main/res/layout/activity_int_imp_pick_up_detail.xml index 4ee37f8..b761ccc 100644 --- a/module_gjj/src/main/res/layout/activity_int_imp_pick_up_detail.xml +++ b/module_gjj/src/main/res/layout/activity_int_imp_pick_up_detail.xml @@ -3,10 +3,10 @@ 国际进港提取出库-运单详情(5.5 寸手机版专属页面,无平板变体——平板端无入口) 对应设计稿 09_提取出库 的 page-detail: - 蓝头卡(运单号 + 绿点提取时间)+ 红标签「国际进港」|业务类型 + 品名大标题 + - 两列 KV(件数/重量/特码/代理/始发港/目的港/航班日期/航班号/库位橙标签/提货单号) + 蓝头卡(运单号 + 绿点提取时间)+ 红标签「国际进港」+ 品名大标题 + + 两列 KV(件数/重量/特码/代理/始发港/航班日期/航班号/库位橙标签/提货单号) + 绿头「提货信息」卡(柜台办理人/时间;已出库追加出库人/出库时间行)。 - 「目的港/业务类型」为 pageQuery 出参缺失字段(见问题清单),空值兜底为双横线占位。 + 「目的港/业务类型」后端无对应出参且确认按平板端口径不提供,已移除;出库人绑 refUserName。 --> @@ -90,7 +90,7 @@ android:orientation="vertical" android:padding="16dp"> - + - - - - - @@ -181,7 +166,7 @@ - + - - + android:layout_height="0dp" + android:layout_weight="1" /> @@ -316,7 +298,7 @@ android:layout_height="wrap_content" android:layout_weight="1" title='@{"出库人"}' - value='@{bean.dlvName.empty ? "--" : bean.dlvName}' /> + value='@{bean.refUserName.empty ? "--" : bean.refUserName}' /> - + + value="@={viewModel.paymentDateStart}" /> - + hint='@{"请选择结束日期"}' + title='@{"缴费日期止"}' + type="@{PhoneDataLayoutType.DATE}" + value="@={viewModel.paymentDateEnd}" /> @@ -107,30 +107,6 @@ - - - - - - - - - From 68e6c7c52b9350b91dd810d7034c525b39d1d1e9 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 9 Oct 2026 07:33:43 -0700 Subject: [PATCH 26/29] =?UTF-8?q?feat(=E8=BF=9B=E6=B8=AF=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?):=20=E4=B8=89=E6=A0=BC=E7=BB=9F=E8=AE=A1=E6=94=B9=E5=8F=96=20p?= =?UTF-8?q?ageQueryTotal=20=E5=88=86=E9=A1=B9=20storedNumber/departedNumbe?= =?UTF-8?q?r=EF=BC=88=E9=97=AE=E9=A2=98=E6=B8=85=E5=8D=95=20#30=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 已入库/已出库由「已加载数据客户端计数」改为服务端全量口径,删除 phoneLoadedList 累计逻辑 - 内网实测:全量 123/119/4,outState=0/1 分别 119/0 与 4/4 口径自洽;当日 1/1/0 与 App 一致 Co-Authored-By: Claude Opus 5.5 --- .../gjj/viewModel/IntImpQueryViewModel.kt | 27 ++++--------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpQueryViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpQueryViewModel.kt index 2dd1708..01725ed 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpQueryViewModel.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpQueryViewModel.kt @@ -65,14 +65,12 @@ class IntImpQueryViewModel : BasePageViewModel(), IOnItemClickListener { val businessTypeList = MutableLiveData>(emptyList()) // ==================== 5.5寸手机版专属 ==================== - // 三格统计:已入库 / 已出库(总票数复用 totalCount,为服务端全量口径) - // pageQueryTotal 无分项统计出参——已入库/已出库为「已加载数据」客户端计数口径, - // 与卡片状态标签同一判定(dlvTime / inDate,见 IntImpQueryBean) + // 三格统计:总票数 / 已入库 / 已出库,均取 pageQueryTotal 出参 + // (wbNumber / storedNumber / departedNumber),服务端全量口径 val storedCount = MutableLiveData("0") val outboundCount = MutableLiveData("0") private var phoneExtrasEnabled = false - private var phoneLoadedList: List = emptyList() /** * 手机形态专属初始化(Activity 在 DeviceUtil.isPhone() 时调用)。 @@ -183,14 +181,6 @@ class IntImpQueryViewModel : BasePageViewModel(), IOnItemClickListener { }) { onSuccess = { pageInfo -> pageModel.handleListBean(pageInfo.toBaseListBean()) - - // 手机三格统计:对已加载数据做客户端计数(平板不触发) - if (phoneExtrasEnabled) { - val pageItems = pageInfo.list ?: emptyList() - phoneLoadedList = - if (pageModel.page <= 1) pageItems else phoneLoadedList + pageItems - updatePhoneCounts() - } } } @@ -202,20 +192,13 @@ class IntImpQueryViewModel : BasePageViewModel(), IOnItemClickListener { totalCount.value = (data?.wbNumber ?: 0).toString() totalPc.value = (data?.totalPc ?: 0).toString() totalWeight.value = (data?.totalWeight ?: 0.0).toString() + // 手机三格统计分项(平板布局不绑定,无影响) + storedCount.value = (data?.storedNumber ?: 0).toString() + outboundCount.value = (data?.departedNumber ?: 0).toString() } } } - /** - * 手机三格统计(已入库/已出库):与卡片状态标签同一判定口径(dlvTime / inDate), - * 统计范围为已加载的列表数据。 - */ - private fun updatePhoneCounts() { - outboundCount.value = phoneLoadedList.count { it.isQueryOutbound }.toString() - storedCount.value = - phoneLoadedList.count { !it.isQueryOutbound && it.isQueryStored }.toString() - } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (resultCode == Activity.RESULT_OK && data != null) { when (requestCode) { From 6f813f9cff2914cdfef1c01c09bafd45491e283b Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 9 Oct 2026 07:34:59 -0700 Subject: [PATCH 27/29] =?UTF-8?q?feat(=E8=BF=9B=E6=B8=AF=E7=A7=BB=E5=BA=93?= =?UTF-8?q?):=20=E7=A7=BB=E5=BA=93=E4=BA=BA=E5=8F=96=20opUserName=EF=BC=8C?= =?UTF-8?q?=E5=B7=B2=E7=A7=BB=E5=BA=93=E7=85=A7=E7=89=87=E7=BB=8F=20movedD?= =?UTF-8?q?etail=20=E5=9B=9E=E5=A1=AB=EF=BC=88=E9=97=AE=E9=A2=98=E6=B8=85?= =?UTF-8?q?=E5=8D=95=20#32~#34=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #32 fdate/fno/spCode 后端已实装(search/searchMoved),手机端原有传参零改动生效 - #33 searchMoved 已回填 opId/opDate 并新增 opUserName:详情「移库人」改绑姓名(回退 opId) - #34 新增 GET /DomImpMove/movedDetail:已移库运单(列表无 mawbId)拍照页按 moveId 回填照片 - 已移库运单 searchMoved/movedDetail 均无 mawbId,而 modify 以 mawbId 定位(实测返回「未能获取到运单id」), 提交前给出明确提示,不再发出必失败请求;缺口已登记问题清单 - 内网实测:fno=MU2222 待移库 0 / 已移库 2 与直调一致;详情移库人「张三」 Co-Authored-By: Claude Opus 5.5 --- .../detail/GnjMoveStashDetailActivity.kt | 2 +- .../stash/list/GnjMoveStashListActivity.kt | 2 +- .../stash/photo/GnjMoveStashPhotoActivity.kt | 6 +++++- .../stash/photo/GnjMoveStashPhotoViewModel.kt | 20 ++++++++++++++++--- .../layout/activity_gnj_move_stash_detail.xml | 2 +- .../module_base/bean/MoveStashBean.kt | 8 +++++++- .../lukouguoji/module_base/http/net/Api.kt | 7 +++++++ 7 files changed, 39 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/detail/GnjMoveStashDetailActivity.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/detail/GnjMoveStashDetailActivity.kt index bc83161..efb74e3 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/detail/GnjMoveStashDetailActivity.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/detail/GnjMoveStashDetailActivity.kt @@ -33,7 +33,7 @@ class GnjMoveStashDetailActivity : /** 「异常照片」加号槽位 → 拍照上传页 */ fun openPhoto() { viewModel.dataBean.value?.let { - GnjMoveStashPhotoActivity.start(this, it.mawbId, it.wbNo) + GnjMoveStashPhotoActivity.start(this, it.mawbId, it.wbNo, it.moveId) } } diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListActivity.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListActivity.kt index 3f1de6c..e7c3fd6 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListActivity.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListActivity.kt @@ -90,7 +90,7 @@ class GnjMoveStashListActivity : /** 浮层「拍照」→ 拍照上传页 */ fun openPhoto(bean: MoveStashBean) { bean.actionMenuVisible.set(false) - GnjMoveStashPhotoActivity.start(this, bean.mawbId, bean.wbNo) + GnjMoveStashPhotoActivity.start(this, bean.mawbId, bean.wbNo, bean.moveId) } companion object { diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoActivity.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoActivity.kt index 971cb30..0382a3f 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoActivity.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoActivity.kt @@ -33,12 +33,16 @@ class GnjMoveStashPhotoActivity : } companion object { + /** 已移库运单的 moveId(movedDetail 回填照片用) */ + const val EXTRA_MOVE_ID = "moveId" + @JvmStatic - fun start(context: Context, mawbId: String, wbNo: String) { + fun start(context: Context, mawbId: String, wbNo: String, moveId: String = "") { context.startActivity( Intent(context, GnjMoveStashPhotoActivity::class.java) .putExtra(Constant.Key.ID, mawbId) .putExtra(Constant.Key.CODE, wbNo) + .putExtra(EXTRA_MOVE_ID, moveId) ) } } diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoViewModel.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoViewModel.kt index 9ad8f53..8f78ac6 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoViewModel.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoViewModel.kt @@ -37,13 +37,17 @@ import kotlinx.coroutines.launch * 国内进港移库「拍照上传」ViewModel(5.5 寸手持端专属页面) * * 图片选择/预览/删除复用 module_base 的 ImageSelectNewViewHolder(末位加号槽位)。 - * 已有照片经 DomImpMove/detail 回填;提交走 DomImpMove/modify 最小体 + * 已有照片回填:待移库经 DomImpMove/detail(mawbId),已移库经 DomImpMove/movedDetail(moveId, + * searchMoved 出参不含 mawbId)。提交走 DomImpMove/modify 最小体 * (mawbId/remark/picNumber/pic/originalPic),与平板移交编辑页同一链路。 */ class GnjMoveStashPhotoViewModel : BaseViewModel(), IOnItemClickListener { var mawbId = "" + /** 已移库运单的移库记录 ID(searchMoved 出参),用于 movedDetail 回填 */ + var moveId = "" + /** 运单号(副标题展示,由列表带入) */ val wbNo = MutableLiveData("") @@ -59,9 +63,14 @@ class GnjMoveStashPhotoViewModel : BaseViewModel(), IOnItemClickListener { fun initOnCreated(intent: Intent) { mawbId = intent.getStringExtra(Constant.Key.ID).orEmpty() wbNo.value = intent.getStringExtra(Constant.Key.CODE).orEmpty() + moveId = intent.getStringExtra(GnjMoveStashPhotoActivity.EXTRA_MOVE_ID).orEmpty() - // 已有照片回填(pic 缩略图 + originalPic 原图),末位补加号槽位 - launchCollect({ NetApply.api.getGnjMoveStashDetail(mawbId) }) { + // 已有照片回填(pic 缩略图 + originalPic 原图),末位补加号槽位; + // 已移库运单无 mawbId,改按 moveId 走 movedDetail + launchCollect({ + if (mawbId.isEmpty() && moveId.isNotEmpty()) NetApply.api.getGnjMoveStashMovedDetail(moveId) + else NetApply.api.getGnjMoveStashDetail(mawbId) + }) { onSuccess = { detailBean = it.data ?: GnjYiKuBean() val picList = detailBean.pic.split(",").filter { p -> p.isNotEmpty() } @@ -88,6 +97,11 @@ class GnjMoveStashPhotoViewModel : BaseViewModel(), IOnItemClickListener { * 确认提交:先补传未上传的本地图片,再按三字段规范提交 modify */ fun submitClick() { + // modify 以 mawbId 定位运单;已移库运单 searchMoved/movedDetail 均不返回 mawbId(后端缺口),无法提交 + if (mawbId.isEmpty()) { + showToast("已移库运单缺少运单ID,暂不支持提交照片") + return + } (rv?.commonAdapter()?.items ?: emptyList()) .asFlow() .map { it as FileBean } diff --git a/app/src/main/res/layout/activity_gnj_move_stash_detail.xml b/app/src/main/res/layout/activity_gnj_move_stash_detail.xml index bd97b5a..fd40e5c 100644 --- a/app/src/main/res/layout/activity_gnj_move_stash_detail.xml +++ b/app/src/main/res/layout/activity_gnj_move_stash_detail.xml @@ -244,7 +244,7 @@ android:layout_height="wrap_content" android:layout_weight="1" title='@{"移库人"}' - value="@{viewModel.dataBean.opId}" /> + value="@{viewModel.dataBean.opUserDisplay}" /> + /** + * 国内进港移库-移库完成详情(已移库运单无 mawbId,按 moveId 查,含 pic 三字段与移库人) + * 接口路径: /DomImpMove/movedDetail + */ + @GET("DomImpMove/movedDetail") + suspend fun getGnjMoveStashMovedDetail(@Query("moveId") moveId: String): BaseResultBean + /** * 编辑-国内进港移库(新接口) */ From 5e8fe7d69dfd5fe8bc5f7cc1c582317499f09fcd Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Fri, 9 Oct 2026 07:44:57 -0700 Subject: [PATCH 28/29] =?UTF-8?q?fix(ULD=E7=AE=A1=E7=90=86):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E/=E4=BF=AE=E6=94=B9=E8=A1=A5=E5=85=85=E6=9C=80?= =?UTF-8?q?=E5=A4=A7=E8=A3=85=E8=BD=BD=E5=AE=B9=E7=A7=AF=E3=80=81=E6=9C=80?= =?UTF-8?q?=E5=A4=A7=E8=BD=BD=E9=87=8D=E4=B8=BA=E5=8F=AF=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E5=BF=85=E5=A1=AB=EF=BC=88=E9=97=AE=E9=A2=98=E6=B8=85=E5=8D=95?= =?UTF-8?q?=20#36=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 联调发现 saveUld 缺 maxVolume 或 maxWeight 时后端直接 500,手机新增表单(原仅详情展示两项)必然失败 - 按平板表单口径改为新增/修改可编辑(数字键盘,新增必填)并前端校验 - 内网实测:PMC12349JG 新增成功,source/inStoreTime(补 00:00:00)/nowPort/maxVolume/maxWeight 均落库,测试数据已清理 Co-Authored-By: Claude Opus 5.5 --- .../page/uld/edit/UldEditViewModel.kt | 9 ++++++++ app/src/main/res/layout/activity_uld_edit.xml | 22 ++++++++++++------- 2 files changed, 23 insertions(+), 8 deletions(-) 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 76d5c8c..7f51662 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 @@ -107,6 +107,15 @@ class UldEditViewModel : BaseViewModel() { showToast("自重不能为空") return } + // saveUld 缺最大装载容积/最大载重时后端直接 500(内网实测),提前拦截 + if (bean.maxVolume.isBlank()) { + showToast("最大装载容积不能为空") + return + } + if (bean.maxWeight.isBlank()) { + showToast("最大载重不能为空") + return + } if (bean.inStoreTime.isBlank()) { showToast("入库时间不能为空") return diff --git a/app/src/main/res/layout/activity_uld_edit.xml b/app/src/main/res/layout/activity_uld_edit.xml index ef2af3c..d18fcb4 100644 --- a/app/src/main/res/layout/activity_uld_edit.xml +++ b/app/src/main/res/layout/activity_uld_edit.xml @@ -172,23 +172,29 @@ type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.INPUT}" value="@={viewModel.uldBean.uldWeight}" /> - + + type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.INPUT}" + value="@={viewModel.uldBean.maxVolume}" /> - + + type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.INPUT}" + value="@={viewModel.uldBean.maxWeight}" /> Date: Fri, 9 Oct 2026 07:44:57 -0700 Subject: [PATCH 29/29] =?UTF-8?q?docs:=20=E5=90=8E=E7=AB=AF=E5=8F=8D?= =?UTF-8?q?=E9=A6=88=E8=81=94=E8=B0=83=E7=BB=93=E8=AE=BA=E5=85=A5=E5=BA=93?= =?UTF-8?q?=E2=80=94=E2=80=94=E9=97=AE=E9=A2=98=E6=B8=85=E5=8D=95=20P=20?= =?UTF-8?q?=E5=88=97=E7=BB=93=E8=AE=BA=20+=20=E6=96=B0=E5=A2=9E=20#35~#41?= =?UTF-8?q?=EF=BC=8C=E6=9B=B4=E6=96=B0=20api-doc=20=E5=8F=A3=E5=BE=84?= =?UTF-8?q?=E4=B8=8E=20CHANGELOG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - documents/后端接口对接问题清单.xlsx 基于后端返回版本(保留其解决方案列与截图), 新增「前端联调结论(2026-10-09)」列逐条记录 #1~#34 结论,追加联调新发现 #35~#41 - api-doc.md 追加 2026-10-09 最新字段口径;CLAUDE.md 更新待办与新坑(数字输入框光标跳位) Co-Authored-By: Claude Opus 5.5 --- .../skills/phone-adapt/references/api-doc.md | 27 ++++++++++++++++++ CHANGELOG.md | 19 ++++++++++++ CLAUDE.md | 11 ++++--- documents/后端接口对接问题清单.xlsx | Bin 24648 -> 691210 bytes 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/.claude/skills/phone-adapt/references/api-doc.md b/.claude/skills/phone-adapt/references/api-doc.md index 2354a46..187b94c 100644 --- a/.claude/skills/phone-adapt/references/api-doc.md +++ b/.claude/skills/phone-adapt/references/api-doc.md @@ -158,3 +158,30 @@ curl -s -X POST "http://192.168.1.250:8093/IntExpOutHandover/pageQuery" \ 用它做「参数是否生效」的 A/B 对比(同条件只改一个参数看 total 变化), 再回 App UI 走一遍确认端到端链路。UI 里的滚轮日期选择器可用 `input swipe`(慢速 500ms、每次 3 格 ≈ 396px)驱动,滑完截图校准。 + +## 2026-10-09 后端反馈联调后的最新口径(与上文冲突时以本节为准) + +后端在问题清单补「解决方案」后逐项内网实测的结论。**通用规则:后端对手机端新增筛选维度一律答复 +「与平板端查询参数保持一致」——手机筛选只放平板已用的入参;文档里定义了但平板没用的入参, +多数实测也被忽略(agentCode/spCode/dest/opId 等),别再按文档加筛选。** + +- **统一统计 DTO**:各 `*/pageQueryTotal` 出参现含 `uldNumber`/`storedNumber`/`departedNumber`/ + `notClearNumber`/`clearNumber`/`waitCheckInNumber`/`checkingNumber`/`flightNumber`(`ManifestTotalDto` + 已补齐)。分项统计一律取出参,**不要再按状态入参多调几次 total** +- `IntExpOutHandover/pageQueryTotal` 已修复(与列表一致);Tab 角标取 `uldNumber`(板箱数);无交接人入参 +- `IntExpMove/pageQuery` 出参新增 `flight`("20260924/MU2222")/`businessName`/`opUserName`;已移库 `opId`/`opdate` 已回填 +- `eqm/uld`:状态维持两态;`source`(空运/陆运) 出参与保存入参支持、**查询入参不支持**;入库时间 = `inStoreTime` + (date-time,**只传日期 400**)、所在港 = `nowPort`;批删 `deleteUldBatch`(Body 为字符串数组); + ⚠️ `pageQuery` 带 `uld` 即 500(#35);`saveUld` 缺 `maxVolume`/`maxWeight` 即 500(#36) +- `IntExpCheckIn`:`listRecordByWh` 出参 `opUserName`/`trayNumber`/`trayTotalWeight`; + `checked/pageQuery` 出参 `passageWay`;`splitCheckIn`/`completeCheckIn` 托盘入参 = `trayNumber` + + `trayTotalWeight`(数量×自重);`arriveFlag` 已回填("0" 正常/"1" 提前运抵); + ⚠️ `pageQuery` 的 `checkIn` 过滤仍被忽略(#40,统计用分项出参);`checked/pageQuery` 的 `dest`/`opId` 被忽略 +- `IntExpArrive`:入参 `arrivalStatus`("0" 未运抵/"1" 已运抵)服务端过滤生效;`agentCode` 被忽略;补充信息页已删除 +- `IntExpSearch`:**`beginDate`/`endDate` 只有携带 `dateState`(0 入库/1 离港)才生效**;`outState` 生效 +- `IntExpStorageUse`:仅 `fdate`/`fno`/`wbNo`/`location`/`clearNormal` 有意义;⚠️ 列表 total 与统计 wbNumber 不一致(#38) +- `IntImpStorage`:⚠️ `pageQuery` 当前**所有**过滤条件均失效(#37),`pageQueryTotal` 正常 +- `IntImpSearch/detail`:按平板展示 航程 `range`(无经停站)/`unNumber`/`lockState`/出库时间 `dlvTime` +- `IntImpPickUpDlv`:运单号入参用 `wbNo`;出参新增 `refUserName`(出库人姓名,`dlvName` 是提货人);测试环境暂无数据 +- `DomImpMove`:`fdate`/`fno`/`spCode` 已生效;`searchMoved` 已回填 `opId`/`opDate`/`opUserName`; + 新增 `GET movedDetail?moveId=`(含 pic 三字段);⚠️ 已移库运单无 `mawbId`,`modify` 无法补传照片(#39) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8777990..29174c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,19 @@ ## [Unreleased] ### 变更 (Changed) +- 【后端反馈联调 · 2026-10-09】后端在《问题清单》补「解决方案/备注」后,逐项(#1~#34)api-doc 核对 + + 内网直调 A/B + AeroLogic_Phone 模拟器端到端验证,并按后端意见调整前端: + ① 后端已补字段/接口 → 前端对接:出港移库 flight/businessName/opUserName;出库交接 uldNumber 角标; + ULD source/inStoreTime/nowPort + `deleteUldBatch` 一次批删;出港计重 waitCheckInNumber/checkingNumber + 统计、passageWay、opUserName、trayNumber/trayTotalWeight;运抵 arrivalStatus 服务端 Tab; + 出港/进港查询 storedNumber/departedNumber;出港/进港仓库 notClearNumber/clearNumber(统计请求 3→1); + 提取出库 refUserName;国内进港移库 opUserName + `movedDetail` 照片回填。 + `ManifestTotalDto` 补齐后端统一统计 DTO 分项字段。 + ② 后端「按平板端调整/设计如此」→ 前端对齐:出库交接/ULD/计重/记录/出港仓库/进港仓库/提取出库/运抵 + 的手机筛选全部收敛为平板同款查询参数;ULD 状态回归两态;删除运抵「补充信息」页;出港详情移除 + 锁定状态/计费重量;进港详情按平板改 航程/出库时间(无经停站);提取出库移除无出参占位。 + ③ 联调新发现记入问题清单 #35~#41(ULD uld 搜索 500、saveUld 缺 maxVolume/maxWeight 500、 + IntImpStorage/pageQuery 过滤全失效、出港仓库列表与统计口径不一致、已移库无 mawbId 无法补传照片等)。 - 【进港移库归属更正 · 2026-08-03】设计稿 11「进港移库」经确认归属**国内进港移库 (DomImpMove,后端 8 接口齐全,Pad 首页「国内进港→进港移库」既有页面)**,此前误判为 国际进港并按 IntExpMove 约定预接不存在的 IntImpMove 模块(原问题清单 #31 作废)。处置: @@ -29,6 +42,12 @@ `fdate`/`fno`/`spCode` 被后端静默忽略(新缺口 #32)、`searchMoved`/`detail` 出参 `opId`/`opDate` 恒 null 且无姓名字段(#33)、`searchMoved` 无 pic 三字段(#34,前端已规避) +### 修复 (Fixed) +- 出港计重「修改记录」托盘自重输入框:Double 回写导致光标跳回开头(输入 18 存成 81),改为保留输入原文 +- ULD 新增:入库时间日期行仅产出 yyyy-MM-dd(后端 400)→ 保存时补 00:00:00;补充最大装载容积/最大载重 + 可编辑必填(缺失时 saveUld 500) +- 提取出库运单号入参 no → wbNo(与主干平板端修复一致) + ### 新增 (Added) - 「进港查询」5.5 寸手机端适配(设计稿 10_进港查询,06 出港查询的进港镜像;详情页与运单追踪 复用 08/06 已适配页零新增):列表 `IntImpQueryActivity`(module_gjj,首页菜单实际跳转页; diff --git a/CLAUDE.md b/CLAUDE.md index 5e8f56a..ed52806 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1192,10 +1192,12 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = - ✅ **设计稿 11 个入口(01~11)已于 2026-07-31 全部适配完成** - ⏳ **待办**: - `PhoneSearchBar` 接入 AutoQuery 联想(`AutoQueryManager` 目前只对接了 Pad 系组件) - - 进港移库筛选三项(航班日期/航班号/特码)待后端实装 `fdate`/`fno`/`spCode` 入参(缺口 #32)、 - 移库人/移库时间待后端回填 `opId`/`opDate` 并补姓名出参(缺口 #33)后自动生效 - - 出库交接 Tab 角标恒 0:`IntExpOutHandover/pageQueryTotal` 出参恒 0(后端缺陷,问题清单 #6), - 后端修复后角标自动恢复(`handoverState` 过滤本身已于 2026-07-29 实机验证通过)生效 + - 联调新发现的后端缺口 #35~#41(ULD uld 搜索 500、IntImpStorage 列表过滤全失效、已移库无 mawbId + 无法补传照片等)待后端处理,详见问题清单 +- ✅ **2026-10-09 后端反馈联调完成**:问题清单 #1~#34 逐项内网直调 + 模拟器端到端验证,结论写入清单 P 列。 + **后端口径:手机筛选一律与平板端查询参数保持一致**(不为手机新增入参);分项统计统一取 + `pageQueryTotal` 出参(`ManifestTotalDto` 已补齐分项字段),不要再按状态多调 total。 + 最新字段语义见 `.claude/skills/phone-adapt/references/api-doc.md` 末节 - 📋 **接口对接**:适配中发现的后端接口缺口统一记录在 `documents/后端接口对接问题清单.xlsx` (按模块/页面/接口定义/接口地址索引,与后端对接的正式文档,每页适配完必须维护); 接口入参/出参一律以 api-doc MCP 为准核对,流程见 @@ -1288,6 +1290,7 @@ adb shell am start -n com.lukouguoji.aerologic/com.lukouguoji.gjc.activity.IntEx | 通过 `Intent.putExtra(Serializable)` 传递的 Bean,切换其 `checked`/`showMore` 等状态时崩溃 `NullPointerException: ... on a null object reference` | 这些字段标了 `@Transient`(= JVM `transient`,本意是避免 Gson 网络请求序列化 `ObservableBoolean`),但 Java 对象序列化(Intent 传递走的机制)会跳过 `transient` 字段的恢复,反序列化后是 null | 接收方 `initOnCreated` 里对列表做 `.map { it.copy() }`——`.copy()` 会重新走一遍类体初始化逻辑,用全新 `ObservableBoolean(false)` 补上 | | 布局构建报 `Error: The string "--" is not permitted within comments` | XML 注释中出现连续双横线(如写"兜底 \"--\""),XML 规范禁止 | 注释里改用文字描述(如「兜底双横线」),代码绑定表达式中的 `"--"` 不受影响 | | 多选页手机版点「全选」后底部「已选 N 项」不更新(单卡勾选正常) | 批量勾选在 `checkAllClick` 里直接 set,不走 FlowBus 的单卡 EVENT_CHECK_CHANGED 事件,`selectedCountText` 只在事件回调里更新 | `checkAllClick` 末尾自行同步 `selectedCountText`(平板布局不绑定该字段,无影响) | +| 手机版数字输入框(`PhoneFormRow` 双向绑 Double 的 `xxxStr`)输入 "18" 变成 "81" | getter 由 Double 反推字符串("1" → "1.0"),与输入框文本不等触发 `setText`,光标回到开头 | Bean 里保留输入原文(`@Transient` 私有 String),getter 优先返回原文(参考 `GjcCheckInRecord.trayTotalWeightStr`) | | XML 里 `bean.a ?? bean.b` 兜底不生效,字段明明有值却显示占位符 | 网络层转换器把 JSON null 归一成空串 `""`,DataBinding 的 `??` 只判 null 不判空串,永远取到左侧的空串 | 在 Bean 上加计算属性做 `isNullOrEmpty` 双兜底(如 `agentDisplay`),XML 绑计算属性(进港查询/出港查询代理人已踩过) | --- diff --git a/documents/后端接口对接问题清单.xlsx b/documents/后端接口对接问题清单.xlsx index fd2b823f3a6ef4d5a30cf65c40550e4840acb7cc..547946ae9393089e8a229fda1f887f1587078704 100644 GIT binary patch literal 691210 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%0ATj~Jz)|VF^K_y z0+1FHR&`4|PIvWERa@-O+)FY)NT5G!7H_&y~*O{wlJUm3zoLwa@ zVr)UCqm#oC?xdj1&eNFk%ryRHZzO1PHO^ieN&%xrzsOv~77HldVGc*Lu7H@)rGqG26=eEWY8?4}g=Nw*V zNK%DdFW^h?+-nBua1<2)Vn8`u%88&cBr#M$(M%rk^BFjR5^3S6wS&3J^D5J@g@3x? z5>1@DV}^F&JC*aDPS6@;Nj($**lj-snWhL1!z0hE)HiWvJlnPOZgELn;@CE)%Ys&u ziZjk>LwIn-4o-j25_zCfiyXLInZDWAc~R2v7%@BavZPJ>m}UmiiKeelw>^V>y60og zSS3u0KpHJD?`3!IxM(vdD%D6OD!LDKs(OX}=_oSIx&`ljrFDSpvw}WUU1L>qYl_gk z7i7{~jfw5-*L@jQvLI)3fX+J7j7fV?{K?0Qv_V7VGlt;2uI#;gfp|vJ4zbjhlRZh) z^;{UZ&?V}pcRX7~-4XOm>eM=U%YMJjAuQdf1>NdpwQT-o(otjC>U^yFWJu#?WAj0! z8A`5w`^kKX+Udm=$Lpd&H5>rw=TZweoI0NQh4Vx`Z5ic@?otX64o{oD3qqny6c_=s z2f>H%ZUYDm@{89cTh&KtS}08EUHKaFZSChKiqC#P}NqbzhOA3o z+0#(IsWy#M$rEI;lk)CXdAsgz>hePsc|CZ6v1?t(%vL3BKAkf%hB!0uZAfAi*>7LS zp9h4yTplgpxb;JC42`lR1oNBc+x!e1T^}1y|wOoQ~MA~LBgi?d6rRp2LLACC3B#uFt6wOvpS@m9^>g*ySfY!PrD6#`~n(p zFVHs4t~LIXZzppSIPG!Awx|RCnvJ-bS=)Iq*d~N)2OT&D4p2l8Rf6rmQx48Y-=+?_ zHWA{&b_%cOA^}vGUS1P(NRd=_h}T!*`ey>9Bz7fzaN`QCLw22R=$8S8C|?6<>#(eD zMMOhXf|Ee~JZ49K0(v=mZ~ET846F_j^RO8ssWt+uW;ytD>>t6s>ns+Cq7*qt^Ixa9 zo`gH3q#^Wg|BlQPww)?;5m(E~his&BZ5rw8&xbFxlu?-QvnPD_JeD$sRgUwMD!&^c zcKvbcjSF>8_;;QMJD0W5j3f}E5i2$yR{PU)5>Ik%WkW2|(hNYm|sRTj6dYn2wcUu|L zIxUs@Hx_JPH>Z)5RV__D<#)4h@Zo;Q3DY>=-Cg>JN6L=-M)4I-QE{NWQak$aNc4A-27&Sg5bPyT}WD0>E`o-tpLh8hOk#G&;zhbx(@edwqmI}i~Q z%OdC0j3n5v_!42De%0s#RXq~R6poTi{8ixFyO=qM0K91(3u>{q;TA?QqLEtFPUfyqR8qXO_zJ!~k{X+;@vY<@_lqh>ZPC4=l7dqpOs6Foq&_ zGF4c)6lF2z$I~%{TNmsx zZt{`jOwjti08a8vKbYTguJUKMLJLQ{oZGFHpe(x+xktbgrkjcSdsrFcb7|4&RPxb! zS1ktGm{_yi=+ffNijo-oL`~!1(VRU&W^Sv^M;RuE-N%Z$ckp6PR&x~u01zjMraF;G zdm~YC64FTs&-#JErOL=IV%9~~b#gIk5d$VffNWwim|(>yX4cu7bUt$K3|TzQ@(b(6 zJ-b-!O|!Fn1NjHUkpn@pXTlUrbi^&JUk~Z4nIu%0&^Bz}F51w^qT^|Z)~JE0bD@mz0rN9yf6?P&N+q~37^FA$+LDRbmt?48(>IRoO92K zeM+5=IF75g!AD=!k#5L0Gz!u@V2d9PsO)m0-Ks zT|fPmAmzKG!O^JzZ9Bch z@YucMuSZw2&c|?jk3aw3_lpu0GsUYC9P$uoT5qxN285~kg2|)_!e9=zYuiLLJWUa# zdqES_Z#uI0d`?DmuzTcw{_m* zZ&exq?gM`?nVO`2aql<^+!pE<5aMIGAy=PjqQ2`XG$pg8eHDqK(3|O5Ec_+;?%Bw? zy>jW(7_#8g>UyY|Ua|Q&sMTp4@uxo^6pWHxONRPAbR#h}3X&}Av-*zPo2M}8#U^mu zwJ(ZgQ2UCdc2WCmWMglY;3J<*jOAkZD#Jqk>h5(AZ|Vi{yWlYoRvIb^#lyubeP*b8 zxV4bI#nE~JDAL9J!CsR^Y4aRGKltfRZMw$t%k#$UmIY4-2+BMXNnDr&6!Pn|ljvJA8_z`l>%T?Mlkbn50s*agR@<=1wwMo}?ESU*L>* zoZ58P)EV%-<8Iw*>i^KOc3{IwyY78EhO_w_sR49H3~dUTy}Q2aT(S4GV2IS?KG+O@ zFycw2+u9F7J8DVuF?sYBxK2+`idjbi#5}{+I`WkcY{R`I?C+L)Tu)SH6I~<`95W|$ zNv2%g#t3HjTw!sRA9HLZ9iy>YA8zy_1yPf1J;OCQ|3}GA$ME@*G3+DMAUc zi!7~TVT#762rct5b9NEw-ImSgu&Gj=(%oV+YaTz18OB z+v}_5Nki+?CDtW!%FQzCR^MhNS=FH_y5Qd6{jI3hLGS4!?T3eqn={r*>-?WdTIjz+ zGND#FrZ)1yeV%UV50g`!-MTNBOZoVP>g_=9Cw+b8aX28fI{Mw`j}7V#nTm5L(AAow z%aL}(7sok-Mu`5YAJxp4eEd9F9(LP7!DYv$Wt!GAKV<%KFM%mrg^L2(_rbLxnT;Px z4svoJyD%Zwv_eOokDe3!t6lAl$yOfAU%4#rxySo{I68j#)PF*s>-Dgqpog>$9f$H1 zT~xFMh;v?&{>&rr$y%i^Vyc|?c?AG%{o$_q z$RTJ&jYd8X1CP!qfG?}M*Y($uBSNX728%B*Nva+JZvApP8?_cE2mCkAi@MFao8)w} zvvd^0&K|!9Fq>hf`#hMr)*DN#kb}5UstjqiqGqpE% zs(jCn)t9n3uoIx*-@m`7*_3{rsai_w3((W(9|bSX{hn2Ol-amtvG#?eV9{oL%73af zI@N>aca8seOC92ZlGDBCy`}XSLE_k$*=R-YUB2JS^1hwG3My`Ym3eCpqBT9yPQumD z4o2#UJY?_~Nc3(}kdmEg;k7`&Q{dtdKX0O7JvJMqW%<}hDdduEvzcdJOeR?9`it;v zJ?imHqhXp#NM3x^L>ec4-Jsb8Y<7HrBCvjU36XUT`)3%NDH6;(K3AwPtLkbn&zDkl=b!y;W5sn1N!3R02V-_uDV? z{H;bKg!(CraK3vZXSk7!zZ-32?-5`D;1K`No}C;giDun%#5UaPyxl=}q4sJIx9?GLb1<|Y{Ai9+k4 zTs8y`5R;KEG$O(FoECf-;A`ejyC~)RXExBxG7A6ZHzPnF{OK5)+1=9AtjtrUMVOj4#>^}=&gkc!3Uqo= zSebRbHbhLBE*d4D7v3fxvbFPowo6Mj;XrI1hk%$5B+ehyjOk0&=}jE;ncf`jOqm89 z#5On=-f35atmaUw#t09QwlpVvpDM z2jN|(mHcmRvgV~=0HOF;9*?P|Sr-x9A88Be8#q5Ep0~;u*1Rz$qa~tIVS%?V)!mu8 z&Tiv+7SInbwWXLKmzh}Wm&E!LexFxMt}Ai1J4W=7jUuINZ+tsMy=h0D_yE66PiY}L z9~GbPjGjs}jjl5pY2)D%m}N5KKQd^-hpza5&D9zO=8B@zSqwKNg}B~>l7e6mFr`nz zE#Myw@|-&1jT>*4>343WKPQtC#JL{?-lv+uphm@hiH$hs9LfLZOdOD>zW{%r9AwmJ6rlUx%QbWWF1B z=+Sf)kc;ruAbiQKS&iw^uu-3v(nTKk_UL%zmBz@xgp;fupKYJIn1(k9#!pQLV z^V-F7&gu$919f|eZQhSuUPhhoUv#@?TzKW_%lC4IJG%M=3^L~8LScZ^4qJ1%>+hKG z0M&Vv04{?|gR<)bLCBLa*-9O&=@ZeX(}fha?nhNrew7i>N7EH*jKkxU;^Ka5Ugv3j z+M|LQW~%d)Yp161*qTUA{BKD25-CyN*9`go3|#c!jcrXisk4Cmsnd#$#xQ3j1~p{M z2=GPr{#r0Kd1Adti~QFWSKMD(hR<15WsC3g7HCm>T5WKr+lLx5Jjuo8uUp#6(P4nL zW^?H}TdajMQ`m2%zx?OdpKPm(lzO4OY< z&gyj0;F{2s4c4CELnp4Rx$l@Sj%5z?BWYjH*6{WyU+d|rAt4U-k^A-#K?n6h&%->@L3<$h`ms z)r}sXy!Gm!Tk^jjlpM(vQk3o7&M3vShbzEyy3dFE+T`$6&N~8Wo_SN!VBQNX01)m> zu0XSCq8*-DnG|xiJAT>rv7f1khj3MD*eVi5gu-O7o?>(M(ZT>J z1zw-bW$rk|%ojPTn~-6In6#Ai9^`tae>%Y=7bCr%AycWJZE}Vyyl~5`_ngvNc?^@$ zyVK80IvXETY*`~q)75xRZd#`qc$BVf$KHB#JeT^QBU>J6;c&EBaZ{(k*TqRy_ZIr2 zfCz=6@B_%^>om>4T2#u4SDlOI^n#lilW>@Apy?3{FAR=Zpslgu@apM8=W#T#qeR z!sw-@1?Kmb?}y%y@k-tu{Z!}b<`gkoXdXUrU#cGa0*zWP1FiIC!G(7d)8RTL#oFiG zSJFI05+qm++h2ryCfGbmR0#KIDN`97r4>a9N-P!sp~xP6w~ep(s~?xBHUVM*pM{lK zeV|a%^A#pwqfRf#FFVEGHpZ`W}<}OL*sdbO_(=ju{RQIPwG`}~O+FJeT2tE)gnMRy6_pk0ut)j-V z`~Zc&6`P}k5je^|(72W*sZ^O@&wF_rjUk;@-#YXw?A9i)_+47gSymt@Sk0oZ^E~P$S_akUG`w4bQ-aE{Jux^}}D$V0847Y*kxoJP0d%n$BnnZDZf48x`bCipgdp!#J{p5>@G9}HcJY~A|p;AU><;z}g!pdb=BKV5Zn z^XmaC(8VX#k>Y8-bKQ73O6k3j`rCW$SO)t;3Ju65(HKon3Q`t+$|1KV)oP8J{GU9|zr)*09?8Mg zL!1Bso73d)Bz9*sOIW!#;E{_s)OWWFx(=7vA7({J89{LJFr zt&oJT!Ro)_B^#5V*Ij}$YcEpX!oA;f^@dN8^DoyH$lFV=(67@j4a?3_592yi1Dft* zrZobXSWKZ!qHpG>6YjXMR7|YLImDXtmD%o(03M9wz@Elgua=x*e3%cYH(Rvwsg^@J ztK91-tg_{hrH&_gC%bO2MC-_+kIpojuZ4}LoJy!ZpD#axeJKdZcTsI|X1bLiuM+iR z@Zo^WBSkvqNTE%1wk)2bp@s?)5XzD7Ig@H2aV_3>gqpmwyIYEy@~)j=rz_-1_0&u) z=}E#a-S7AH%+D`O?J{+rpl&M8)(ULJsq%-2Rtq|bJ|p>+YtZ}^=4rihSL|_LyIS4y zwU09^CjA zxW&(7w^9O85xZSoO$p5+ZIcZS{q}MjTok?anVly4CkQa|$k)jZXp}wV5NL0zj;t>0 z*-;0v*ucHA&wl2VK#(>h>vZGDUMI$zBrBpmQE>rUiR#g~V!lvM;akl4J^64)V^!Jm z(Wgf|U3Y(ho%m=g$N-^~{fXSKsFuaVK1V5Wr2qN5+wbbN7@N;11cW7xoEdf1!ow8^ zC8QkBIp=N`QcqR3p41pwy(W_xdjyZq!jnnU3SY(XH(*>2;d$7j+inO%@}PIkGMZ4N}Z zDGCU|rx7*dys|+^P z>kUYPq$i^DfxU_*xdpra1g=Ym<>B)=xxmnVrrGtSgZW%^6F=SiK|FWad1P?ZVSslz ztKN?)dC#+&`qW@51u_iqXDi^)~~>`?aeTkFus zjhvozV=6ioftRe}T7h@DTg{h}vgdg6EAk}cunv9)r_YiLWFpgleH6x*>4n$vJh5}t z^QX-FiXn?b^!1{(^gCP0`bde#cTpeQBoErU-NwYvk_nVeNdy+NeRcl#tn zAb0}KB)hw0SK;ijKQsJ8eoy;+9-1oR-b|l!pcXOIq>=yLpR~npL773kll>a6#esbu zy)%dq8#cgd#w0_S2LPpKYJEZs15f5o!LE6~d!d*B_8_F)`4OV+ z4tQ)(M|vwit~>e8@FF+x^(qIf&~z16)#VV@Fsgo3%k`CAMsDt~&&s{N=O(Cz6aaXJ zF5AXDSf;eA69lvq)P8GJS}4&lF7QM@>3%!UhY|Sk3Bj2*cyFGJ*uj1+w_m ze)&=h=-_)c2qoI4;^AzsKkY3p>{lcA@unur6W+FB6SY}d#$(sb60I7|go@X_^)F$I z)_2Hz5Pqtg4|)|=<1LlzLMRkeN$R%Gyso!X`;0cPwuu}se!F|#-mc&`Z-8q}=GIC~ z`3Yk^@}+K0f}-)s=y)U=pP%f@;Bp*aXm7*STd~s~>{V^GMqQ)##~&<@6J4|N>zrTK zqF&c8-AwMguGMzb2&TS=%v|I?-k5zTw>KktS-rowrMe~WPp$Z#K{D5JRY{5}a)p#1 z!lIB`U$=3Ezv4Pe8?7y7v33`ISxX-E8LFyix#&p7mpV613Nn3!n&=I8v3y~o+bKVI zp=0F!7GE#HM;maj(tG#vJ^eyzimomZq^L2wv2jfkMpu9AUH0rBVpQ3rQw(itm^wCJ zyDxIdThZ_tGr~#s8Yxw?mV8!9U7K#i*18m3a#wh2=+K{PEZ07fdh+~nQGFgRh@ag+ z{ZidE@_}Fvsr;>_xIU2 zNk=R^SEO~t7r#0*fQRGL+?wU#W5>b_RlZ}o!l^3(l+n6u-qB`xTA_bm+&5RvlDWc( zC-EJ5EV%Tyt~Z=k0Y}ZhuLaP*j8bNz1}HXXqiMhhU2-7N)z8h^R+*&xmj33i1l85n z#_T2^Z3G3&5{(GL?)czyWSkK$51A}7smV2)gnad_T9@RnoC$vo6wP-=b+Vm-Hyna% z^_RW&$Qx4GXb#+m4g>wIv<0!)M>y9G?kqXsbFb$TUD>tgZhy}#4 zde@i~j`@4sV6mknvgP(l@(@DEE(DvFFS+?(SVh1fv`<|3C7ap$n_-})hV zf9x(_?rfoh2}<3;^&B4r*6rV*JlIiCr5&FWkRuGMrHEJyc#cxdsrIYRK0)GOq^;=U zYG8jRNvnW*enD^~+9&}pPee-5KB8{{O@?Rz!B?c7j!%wwIr$I2JPuNcMPNJ1h$bqC zP0@dD?NwLi8J?dGe%e z9!fXSyAAYG29ax%LmBla+8cCqJP_`$8D%NX0A?C^IcP=C=;gnZ8fNtB!d$AaLRl5n z;)q#1;Ra=iJfW$?dF%G4oOz*P+!4|KaBl&i0pl)SGJMH;sbP&GwTg;IX=>Ip$(>{>ct!B&x~(ky zJkpmN*k1|S&W(i>fMWgiyo!wT+0Twhy9c?=<_iNRHJ8ToTInw>M0G>Bo%qrFUu%tr zxeOy%)X3x3bjxScZqGD~|Go}I(@>@!z&8^-F-^lLCnH)#iDQL9!8sc){A}|i+|%|o zEJD-|8Q99r&hiC(k>8Ese?u7pt=5&_3!M@%F{e$s;t_N|oF-?!G^Q17<_vSkB3mS0 zqkjIe?9E*`X$1ce>L7N&Ed=C}IU(Xb;lxfNbA&@hlMy}_bnyKWZU=r?mSM5f3Opw| zlo3#cwQ9D}XlgyRT%YO@rcd9|hU~O{m+^1=)R0(;XA;q5=OMUl^v~;PWV`+*>;|GN zk~X)lD(=+t`{w9fJFQ49@r2PcGwIdKgMkawK$-~kZ}#{AKx{zMnzzV5hYEnEpvmT7 z`y3Xx%V=d5429zJn!7Lr!;px79?p~Pw-^4I!1K#q+Q}H>rsM6KrTu)QGJn)dTkU&0 zMHb(3Qp+XbeXi{H@A{1;IKCww zrCDd;63t0})Y2z$SUHGZc<7z2O+u7_ph*7-U98eG)5%PQ2ATraz8M@K)RXkh-)H1k z3NJE%Q=N+|9=%4w{7*zy5c<=HRuWDbFcoQt#5MV17LC`=1cjbfb_0N~SP*_nTBtpx zj%TdSTsx@qOLquh|j3JZmbv zY4UjUPrj%@Z*Qmgh2rhx##@MdBmvxU^K+IJNI zgv7|m-fR8MI(-KN*q?=cu}Ho#(&53u36WEL+;)0EKL9 zIb1o5VqD9R>JmLLh64Ele!WwWP}KjI3I)KxoO^%Zm4@^q=l%_~&cAYl5jLSe8XE;X z;zG$VUw{+v%p+K9fqvZo4GDuzpC08^yk+7s=F=exY`Hemnn$GD+DEgYc$b|}B`8j@ z^k|vyhP6zv6NDiGU01zIYhWk$H#VDXZk^#D%wkTLF7R)^EHvMC>O`o7w4PdJp29-f z6<}i@yJZ^`(9YMtJ*?~ZhNz=Dgg>gFi1RYNNc#wW>HjCu79&#UensL%>~DJsUUkm) zvAas2RoU$47OPq}*ZuYG$kM#9w+jj80WoL#^99;Xcv%C;OJE*`?XTO~^NHG1?$*&H z$zCY2W418gBMFJ=`I!lwNA7%!%A1Po#0>pM@s1}9Lt`tXw#Ril<9qnE&c6nAYihm= zXXg_-&Dqq?zq^|>fA#tw_iL{TBK-H#pdI=@RF403iTQU!(f0_HIs7a;e6_NaaUI@N zrl+mn0J_JV`_)KheK^;+(tj0|G^koN-XIf5EzOW{o3lU87vwE|x0<_L<$0_k~{&;UlqLqpV8cU6TCwvhO6d*}7R=T_$?(??(_gHPY-5-5}K>34QU7RU^6!Y)Hi^#ri(}TY6XsMO z!Q>MdotBm&0l<0NW1ted7>W#RM`|#?`W7XW`}r->wwmQMj}Rc$B<~vC*rvD5A`8fV zDu*h{l!~J6W_;;815GtlW5W0ds z#u@r(H>2QOs8LwAzOXs-J=&=zQGy`NU+8n$Tgk@S<(tgV_r9yvX*{pX);B+qvQai| zBT|}h9U7MmD65w%4;dG_NMcV8;ApliHL#Pz?1x()uH`7wsEN?Pjp$K~$xC2;zxt zLB$xBFri2@>0^z~iq`xh{N*dzV|uh;9!6|M_ zRr#z2=->@8Sp%;i;Ckbl6Y%ZYgJGz1dr}iOytg;uV|Ae=$xP`En3o29`{nZ99-5QS z4#aSdXj92YBRa;`w9b$=|4FOeIHFds;Q^CAha+?UpT)_|sc;_QNf$rFMF~!n6 z4TB+Lcz}wCUm_-&PBI|_4xaT;*i@*RoDyepK=VC=sw1kom{%qnhnh}WmX-H-!zO97 zeW05p15aarVVDMdX(rfE`@+vk4kvk}W~oq*KI&9a&wKW^hta_~uxg*r?yGA~nlMsQ z#zD?*=61i}Ta?()S1kCIm}(qt=AIku;+%3iUf}EgteeG*JCzPpY1lL zbfM`-SupCmic)c`0!f&!OZ|U)q(2EZ>(@EG^S{sttwkR?OwM-&1#ic~sighM9gl<_ zwG?e&?CHEZj`?YWN}<~34lRo!oLng4=Al`~*Ysc%K+8ubqVmy^3;?K%%Nj^kg_Ur8 zeMW-bDj^HrOzY*BDX5tAgr$Gv#qS29s0vJ`^0%6@^hN+3=Sx7KQhnq^@2^ayAtJCQOO9dtA;UErKVOlTFkd|~VHRTs(?qGf20bPlJ%tr4k(pd%h3vV?ax;jRhq#3&{v zFt&17J%84K;fpmN*u+Ea^8-8|d1r*-Hp3G)#W%Mva8qQ^R{G zA<>+95wR{=S46BWG+G$<^T9Y?c@6>C-+f#u(qd!W3i3zFl7QH{uH?tXx z`IisVC{z6J!zeLk{XO2&d`H{&edN>D4c&j{K?eXSRZYLa?}P+h^#p?}DwsVRkR`E9 z^n+gh>3oq968nr?(dyt?+tX(4^1=uQ5>A|GLicE^hnVBdshr+(_-j-=GA}Iv$Ovf= zoBzRG6)gNnv{aDGPhNI=q3^^rOKG=0ePRE5Vw88@T_18BS^7lMQ;Hfb}#`?6IWnf!r)-|>IO zVkeRXPS8fqEersKYsT9YqjB704&YL4<4uWA>UbgJ*_>5-7#0znEET-wpvDQh-Wm$| z%YVs#z+#`(veaYKyIIH|wdRnDk$v^X2o#s@cxqObJHSN`&FN)|KDBNiH$E1(>HaucM%M_uLEd5|H*xR@>;Q zb3l+?YGHZeWX;b;Xxao$kRJeWetbs0jTD$(Kp@L-`QvXtM%(RMvcb5dY5iwX&H-Bn-&I9|38RTy5)aK zth&#~D!zec3|wL}pA>cB4&1ki`w_5Ve#P>I35M`8!sKk)ubPNt$#95S^O6n~Ogi2l zP*YgYxGo7gan2X+nopBlj9E70WV611RoG)B8}Ha^gw0kNlVf_$zD3DER+&CJ$V5X4 zI}uAFBakV`j`_9EAz2|ft;|Q~?#uKnU?cM?I7GB5y!n0Mvv!eIFPrIR6$LU1Ebbau z*5*f?x}Qqnk_scnN>))qoasgUR|*>{LB?PY=Yg^O{U4AKx6q#h`h19&4gg< z0R;kIE?N)tRrb1+i55ylUpff>21g(z7aFXHK}>ne2)h*0dgT>+Y2UAB$Z`)`LS+K{ z_rZD@mk{q8c)!{5B-?h0Hd~^PJJPKVJw?x<(|O<2f1Pu@73J~4mk4HNoPWRlIB8z3 zlU8!f)Cf9cP`2E&ACxd@LusqIo~t3SN|^OPOpm8kLBRRf9E+Fr9V38a-9UhmX!WEbxSRbEvtIUb_bSaSG_5(tEE@OkIixOSnO z@}oA5KhNqiUI~s-`XeYD!E$Kn%Nj*TK-lB?^xITe)}WIy9tm&$u5L|2?+r@%9jD3M zD>=%w-$L;ZdZQcA4-`|`z@DWSk`P|+wX**M>0*Rop2G5yVc>*QU=FNhfbLu)7=KE3 zO!&89ABXw*zlHh#6VzYvhx&8=gZfR#|AYEnK{5YM{jABhv!r}dzCXfycE%4@-Q>Lt zD1%Yquo4T9&zQElK%zz}Hh60w(U)i9$2&cOZ@1L1sG1;#x_6YeV4CMEd7Fswb=egV zY0K8j(`V1YNwnVNNwYc=uQJjHhMK4JPsVJb0pITUu9FAh!A`Qn7eWONW8DCb5weRF6wr4m%?1Plf*6> zxC7h|cxuLO&p#Y>S4!8Pk|f?G-fWo6((1*rM|SDIw$CWE@A}*Nfz*Rn;TEBAy^BN$ z#?A7!L<^LhzKfdU2uMvJ{Dc|EhqN?bMOd)}>;O4&3u>xA*s0enmBI}h`5}=cMx$Km z2!Ns3;922cz4V9$zlV80Q+F#$Uyezi;%V^){35;7#{&-t1bMns-rYi{4Dn%nKfCqk zZWg^Ze?YA-A&<6=mRX+>anDqXQ0O5=I+l24&{zNU(CvDo=)LIky<@$ygsBUEnrFJ* zB;gotu~{XgGuguN?&pH2-5`d@klpm4YHWVlm;8i5`I9J$oLK5Ar$%d20oVzGrD?Eu zwp2-=6kC#yhMk*Ygi%@0`*@g(*zI){x%7>L1i^woCQ?yE*VK@MI znf^%yOeigR56`?73*mwD6@5`Ao`uE6D&bAHJ<3}22=w^UDw^I7%I7I|4n8YaAK>)xObp4DXuC|W{NnQ}tL=9#execa zp;PrapSs81@{8`j9WQ#d7B+BxMUa|moG)#T%t7N{4zu0o!8WjFEf|`j@j2F>4jab6 z>mwc>Hh|sP)7LSHa`aGNq@4k6edwc(y8~(q}(}%N3TD-qZ zmdT)pQ|9v={HHmn`6RCMVb~_qBcH29)creu&`?+%EhnjQt=sh~LW zmjoIyDw#IbHXhZ5^MaG0alDm}_7^|A`^DZ0uM#Z{sfB%z(BUElezht1K;9f}5#w3J z=>27Q_E{5h#WUw~yvFVP(J+gp01_d-wUt&zyhup5Z&!*_Cw23T}XIQv1}EmWU+l` z^CxSJ1JfCRdp8lIq&WRZ;Ch3d!&{;LiwkGxq;yKX+Jbfs%5d8HZ9`4 z^pjfn;0LBeHRKecRds<4f}>N^7EWAwye@L88OxW4whkA$KQ>mtZ3~+#gWV*}Mc`pE zR#=%)Ya8jGWMje-$yEXgHF%l|!78M6gzn|f<(2>t12-&SdP9{n>-G<#-@2T9#<6iC z6QtrgO;-8j^Cy|UkchG%zzEuF2B_-UUZGAP)s-U2?0Ar~*%_P+6jBAm5Eg7>?NOCX zAItA&u*^w1xW0dl3+oF9U~WT^4ZzdV>C@?-2X=;%^t1j%m&Jdclys3?8KApk&%l9% zzIHZ3D|%3MV9&HtK5PL1e!i?>tGfkzMei#LfC}4ep`FiQi0M&!MF8jC3lA{v89|q6 zS8ntoQJrDjSvYLq2at;lk$|x6jAjMo`&==CzAJF0aq+sCz zMuJt*UJBz3U#XWWzSzk?xiqR@f?u&Zn1 zf6aWFWrC)!(>!llH_RXbz$VMA?m?U0=tYDCsU{QVV*U;i$xV3tKfyfq=6^SPy3D^L zL^1}JyB>_uTNc%2=o!J;NoUWCTp4J2U=!to(sDF{^xZFD9h z0PF5%vVrM8;4BIADyyw|7Oy%jz&@%VQ%@RlNeM?oL!BWV%2hM%=I$S)B?%fDMYoh9 z6I{PEeQ>>bunamxd3`L=)Kn*251h_aR~<8_CLPUPi z4ka0fet*%7B7L!G4F6M50RyQ5iZtwfmYvsK`v>c5RI_>7hyEBHaF>C|+(AxC9|_1| zgO)tY^au~dpBjpTMy13kp-q>RU8``1CPvL~ct#dWGTii;W3v3qS_Wi7Dd=CLaW1Ln z!vQ^d@Ab%{V^9EN4$-C%s9omwmEW>^mb~l+@*@XWeA$yc*%{;{~JBQYf z5VQ3h-9Jeudvszc3iTHfW-UHmm>*0Q7B-PX3&bD36Pk(Tq@pZ^J*a@LhIZ*8pIWYJ z-8V>JSG^I#r_0Auq3=WFqb5ro^uy2Mv2*KqJMyk<0(?tHesXD=2}>iU(n(oT;de+R zHBP<8#q5g=L~ScUxRm~mm%YA7w14iq^eGrASXVU(zwm!7j*I|cIPb9X~s z^@byngA8N2-jZpjrY(^Mgt`ae@dsqS!BV<#JF$|tp+v#)joMbce1QD0$7WAz_4=@F ze6z(fozsA5rxM4?N7AJ`V#0m1CNjzp#f=++AS{KQa{sIgJDgC5n#Qw|@x^=}Q9M6^ zFFX?u&K~zci*348)P-4meA~27bXn|qlPxA$R36GTvw%VR@y1@K^45*{eSU2FNtok~ zWUF3dAJ!i-yZ!)gDlCMIUZa-mj(7k-oPEB{5YA_2{^Sb2OpK#oYgQjTt*XqRm}r@~ zET0R#lM5)|GuMbBoFR`*ogP6YTrDt`>aXk?m@q;38Kfh~!;}=RlGwg;tDq}xal*&E zP;}g2a3OJ^f^`wM1aF&F^ZB6M_T-77?ihhMzdobO#1&aj?Cn!NRtFLw)I&ZyRE^f_ zNd~Kw-vaA?^SZvZO|&&$N|rHl!EkT>_(1(0ij-{i~CAxBL3cVYGP8yYGg{l6h zv=#oPL5;Zr$GMeaS^St9t444E15rrRxotKE@&4|x^UFsVSnn&ArAL_%8~N*IMmahD zOyY|~<)UI@W1qJtU#RrJ31{z>T=qmiE3E20me=)ZNd0LPV(3hN*6n6_+eT_Xww4CO zH*i&G81XGFIsXT;7ZMiwq)i{4-v0sN2%CS~JU8-Wo0gh>!?|Y8|JEl>6do;O7Qw2f zBdJfm1N1F!FWmKTr&aJP8pa>bz0iL1cV7N&wN6-cs{Mqs@W0skmvW4X_%i$|uL3vg z{>Q|`1I$<|t=*qz!s+10!eOeM%peDw7ZSMUr$ojGcb}TT;in9|LLr@J{tcwo3qlMFp4!ek9U&CHoyX9ACXf$m`N7) z-@gF9`>OVaeC6&M43ufLnr+rmCxdcuw!`Fd4c9%mp+NlW!veJ>y#*LxV)nUJLssm2 z@?iz4ntFTotcRTj%WDEP>B=+WEKV`V4fRsxIrx&|%jj*eV{#e{xXt3J8ppS2GC%## zW0w~U)005?nM&kbU} z-V;j|xDa0Rx&OBwt{}TIMGjEFCofavp-ZNJ#@8AuQIpXcw|f2KJW8@xiD~K*-y-q% z`~L5skPEY!qn>DWPZ;1jOQVP`!~zGVO2LPT_iqpEgWitUGp=tol$7``pK_ixe|Zsb zFlr~<7NpQGKWte!j}CWZ0eyZEDR#2&k_fJltGC+<8Ty}ZCkULK9x90au9%KIjnVg3 zx1QU2%NZ6vrt(~0-=7Xh@b9D3-74^fJd^fqwXMcO%^FU;f$~eV zXoiO^v5;H;m&gOEKMgzH8xMNqGZy$y^yL^FpXM1StSW4ih%9={z~Cit=~T`%Aw9;sD5Rc2M71)noyC<^vGD`Wv2670@prKpG&{|CB4Ug=lV@4krnzJ zaJNL>lKCH?Af>JFp*!U{E*doGRl5{gqo=RbY~lXJUq=irBzMcIr(UBVgiPamaGpk@ z20g4U4S0i^N2FZP8N%(yfP6nU%Q^F0vsPo4SzBC3`=EM~$O@mZQKJ;&ZJ`f2ey!mL z&FZIOcn`ENKWlAR4M8Jb(`@!XB}F#cJ@#6Q=#S?dI=}R4;pA5wpo*h6z0Y%R z>0VG!zQxN3o5!)!W)H6GfMzfhzXVA#Lu8h)vC$i>8m;aZl}4Y> zfcA2tBy5nroW3$J83gLA??Q*#H)i49;JaL-7Sfd( zNNZFio(Zyf9hdo4&)!_pu_>(j&xd1Y^=oF}Gb}pL2Gp8;G{PL!S7be1kD2ZPMF%iN zeIW1b@i6N)igRByV_B1Dt_b1Tmpz+{AWPvhYT+9?#KvBcNExenAAh)@iH+N62CqJN z&N9#v;7XYzE@@`_ovaCR)n?%l_yr*}Ycr?)eeuc4A;tEX`qrElsgQzv2v^GG>h)al z?Ib3(m7*$hDK@$v;9cR$de-UJW)|}?W`JIP&8_g5#e*A$H{}Jsa4qzhc?PVB1$>c~ zz6_fxfY3N5`v$#)lwaV3+x7NxVg&BxmL~}CdYZp@=C{pc#7*%N<0qsddLoE}Uo;h9 zX8%%!l(rM|i?^86bp05quu>gZ`g&3@EJ9pL=F%&|F0y9H69?gbkE#Z&T}u`&AXTrd z>iEpOMxFO1y@zGjE;Z0xhE|8U^qCi0n z`bFU{B`wIpsPo>gSv^E*JO|_;-Zqt^*JG=7>H4BvCzRRqA zY4<@zaR2>HutA+UyF-P4_c?^kB>a$uAHRpgC-~y2oPtzn7YnubKCfIVkN(ySCS}8L zDHju)<%urEK-`Ac7G{;@W-KyRlwzq1ObT<_fHvSF1*5%*W?1O6%#X4-DH1&Bw$h%I zN5bXl$BNAFjPE_(&s$XoVYqp-7;q|+rPnRvsB2Xc{=D8kFxtyLx&&pr^Hjt}Lea_cGk>@XF_{H}5Y*P^W7eRiOe znm3aizFcWW;n|xsZ?N*sc2{p*OV;S0={qjT7vW2ED+WV{TvyPyW6{X2nWvohwl$Tgz3%r9e%c7-b=2X3OH~?uoB(|jS>f2kA=%KD zpW-(KS1Ij$RPL5x@OR5@fehq)c7aLXABHG#5=aDvJaB%sw=l_nQDfHJuoa!KWIEPZ z^l;-kjMNpj5Pgtxp7mUyX?3z&Pmi-{$d;dNgDVAkA%Q{5>agTSBa?(aAN^x5Ne|fE zbm3{BCc&yr8-RzX{*H1G8eoP}P9k-C#j_TZ!@Ipm zR3b5o-(E0A?%lrYZY24ahyQ&*x}gkIr?NX+MP;+bkw60D(3YiN4$oxaXwH|P+}h+A zHiO>9Qh3kqV($rViTR;*=X9pfnIC)%-ppdwhJD4X$SgeJLq1Nk<4E{|YB&`%ShYwB zx+)5?oMuATrb@GX#5q=F)(jl+JU2jOAofM0`<5jk^~dac6Iyb;{8Q+@D|Whm-;!P{ zd+9qhvuCcb@0}0T>4Rim*=CN?!xUgyK*_p%PuR`iBlun=I;3Dq@v4B$^2y+mOl|+8 z%hH`g1O~s)?Y?1Vq~V9B?APsFK8L)!EWlF!v+$jWy2Z23nwyvwy20(DiysW!zVYfG zbR(Levw^#-ux(Zp&Liu07wp zZRv&x-=OLyoBoST#}kS9wU6<@`3%JQQ-MRYDZRL7Y(Y)TVeu7>oCYsKzybufTWG6x z^O}w2AyrfE@F!!UhRiE9tt>l*7=~AvEDLxKjSww`b2*iXV|(WU=AyY}8=l1AtMNUR z-oeU>aJVWJ|8(!K#& zv3<`R1?>2PWU?(wA${!N8-vFIW|Ki3ziWzP#%GI9qpFv%mbjhFagr;~YyR+T^OlM0 z=y-24CY&6`p#@*zY#y~5Vo*Q>eSQ{sp(%W8TFUDfz12RBPn~*!Xd-a$4N;f`+M^-E zhf&v5Q|R<|w;xns%ZJ7j4^hHzWlDl(lQB?xA3INC#RDT;VVViB?z%G$*?m-ofZCTI z4KPP(^_gdFXN+CURXR#n7F6ES%b#>ye0itN$IQDlk~lu?20pA#hOC~oBd$C%;z~%< zoNneAD>pZvZRFbSiS;FR`=Du%ugh*_R~lHuwhU_DHS)NJmLJ=OBb_vNIs@r}TgW-= z+I66Ek*roXMy!cc9mRF+%^YFpDo#X+0zLqR2*86BzjO7uiMO9Ax~jrITi!@6$LY0R@u4vAMhT^V23v4`(;zcI$xfXBWycVka&kVM z?FwWy-X#Q$Vyq~}`vS??sS(E$aSM_yKva>NiYKRmc+2mIz376-O6X!{h_XIK67J*` zv+^6q5O3=V20RQ73NNfU6E4DKD5rw>KV!yg*&!IIb}jnRGHiFPSLa!voxP$!OuL2oYz0NlFP*vK zUf6tSrOGGV8=>jdoSz*wNjtomlJCk16Mb7{ z_?R6)xL5kZ5s429ZDVU7c;QcBh7}h9xjf=&1ZlPJMG_5iL4&PL@E)TsY5Jx4 zFO-c7>A&lER!hK?oGe@P&841x)oYV5Pa;eb9h;uK+HOud{y1no&wG)tM1i*^6|TB( z3yL~0FePV%Z5|*?O>|M2=!DG>ba2JOKR=i!?^P~@7oi$*lOXydf^*_tWa(T|VaGk&8OHx$6hj2Zc zKYZXtv+gPQ)f{duXoK*+QWq7QT*n$t!;=VLeISn~ecX|Vj+>6K>xkX?D7YOQ`4}8X z_*tN!273v2eLB&D!Ld6(*1FskhzZbAi-Ncb-!B*O&lbvyVR-==q6ZkS_2UPj_M$v5 z!Jwe_sYyCM-qOKB$t%nr#NH6;kW$h!&TJ=z-;e6G=!k2+(5CpNb`L+Upy2DnJ)lto zZEsWTk)L|FGIc)P$8dyaLTK78MAl;rYGZs6og#f11OS+X2S1+9nK~Cu5y$Dch0}V{ zrDvIkB*5t*KD6F$sOJQA5Jx^Ag1HgKA<8ZH2GPG@TLsI#Pb)=Zbe5$H@Y&unTcsKm z#vG)wPR+~2Sfk**?Ne0vL#x))c&rv>n?^}WFl8QS zGl!SSct(L1&(6JIsR^AA*1a7qJZzozV*NhF^c2ITL(XGy(#cpAl`qS)vK4N**b*slyI{o#&qI|QlyFv#7|MSb)8Ie9bc(0YSQxh67|FWHdZ zjdu#BGMzjZOp#Jk4!F6I5j8diZ}O?tv0~?K^(x+b!d7zVdB_-ePxloi!Plf92JUIM zdx>lSu^)kx8o4!LQCE@}_R3iQ1gnS6!BCl3s$C~t^)puZ_y=(9W|Isap|P8mUg8qO z$ipW#89aw1+EMM@E$kaDeKe0R47?QdYy*PIZ*delY72ZBQqE^uaoM#Iw!Fc|?7~2h zUH5`(8PtWs#?Pa?Pv$5c%5x>o62ouXP2%#Zpt5F@wSKE6wfrOi#A*SS;Ger^*-U;}p{)K$p;dK+-wG{)U5 zOtQ~SVq?WM=-lYRjj#&caaE={Xn`9R_Tok<4qxUE4J@ngTtw7Zh)$cCsLRtnzCCW0 zW5@Tcll{Fz)*BM_^GLmT24qXWd@8-5sv)=sVQaQU3Afc&nFzTrr#E3WNX94qc&)_%?lWfbb1C0yRYB`Z+rS?iqQ%1&(16QMirmKw0ed*)* zlIFrNzQEV4JVks4)|+!1nn_(FwU--Lh?|+yBVCy0%9q?qSgyX%@$5JRDO_IZTO=b> zYu^}j+@QW@3+tY~5R8cAZCo^sRMet<^79%%L#;x{^A`niiqQ$L4%2nlt1Lf>FosRB zaIM1zn4m=v(fqKIB6sDr3fC+S#~9ajc@t&wXS5yeUHy{JHhJB5UDwIIuNu}K*u!qR z9m3{0{ScHi8P+A_obXKw>n5O2h&S_+tM8dxgua?tdwKA@GAO@Lg^yl7>U#jOHz2M~ zQBk12=Vw2y4+P$NS)w*N!||Cfyh~wH=H&a!kYg8Z`569A8bIOF_Mu0Y@wmd$`-Vc^ z7{SY!61}5bT;V)yvmrEtw^*?PA90Wjd5cri=DEZ^(~2}sXy1f8G93_g_^%Q8es$e? zGR6pAO?vLw!&FT3uB#}bq5h69lP7FWoWWQt>Hwds6J$z&x3SQRDMtEj?jPJw2DP&a zGJ)yEKAMdtCPV~)mcs$tTns~^aEMjr<`4Q4ueJ3#_rcF;-XP>P(%gB&bmUO)#QrI? zO}205+rr>Q`JcvzQ`ft6^1JUfN-wbqMHd@uF9qdp(a6IhF<1*fyf$V_ui~+zvRhblkU5g zhK-udlAoCdVlK8Aw6#EsYA0u9uxj#ryM7>tCGKrEE?h60Vmsnnzt(w>)_F{xyG1;} z=9&Q!O$YJxU1%~QDY2=hq!vEEsjBNf6g3cs<2+~>I&C#XZbe(SO|8Zvd$G#*Iw>C) z8ob?pmK`i3xyt5MdhTf1DB3B_+JEK;*u*P|j@ELC*GnKAA(vq+jHL5;=ZW!^q3vV6 zHpE{wv4|e>Au@NR69sU~r^7iXlsm^XTqjokI#WGeifF+Z1kXa*;G1of9s zFL`zGzw^GI7h4(2a6t+4o*kHSheC0?w_ydlBnY#9uOCdcYKfjGcy3<)-RFYPqDg}Y z?P~CJzM1REYOJPx_fD?&qB|`X^rqeX{K;PZ*)Y(u=FENpC};-5ck=??NVV|y=pUBX z*)d<83v=3dU3Z2ycx`yBeUuT!#pggFB2c@9SE<`0_hYveR_PxYJ(+m;>DAFGsRcX`?tuw z_IdROd?yYb_bzm^+n68DM+z(zE4w!2(uP zhP!SjMdd28Pq7fz_SquTB9h?1QLUoelYR;``-odaIuADe)_`L7%+FUeA}U2DkQbbY zi(k=XpUacJLz8SC;su=pWm7U#R;oo*0o3t##W0;Kk&FhtjFGCn3(JKl&5 za@kwkxn?R>q+l~Mq!uXcD*KFqw84y*`7M|!T^$5;k0^FJkOTs$4)FyYOI_GJg%7Aj z53cKoL?f0nh`i`91U4z<2Uh50to#JiM`zr}nap#5+Evv1tiArKC;FI50EW_Pf>waE zY-V-B4nkjJ&z^Yq5TpiB)8r77Qqz<7sAN;H;`#)e6Rw0Ki4V|Xmjd=P`rW0D$Jtzy zG;nfmcrI0&D&4#i59`bZZ;r$*TlUDNNxIq8BXM*ZEC3d3LnE$LlS0AJc=qSw zgaZV&R6+spc6@_klKos}g9w}6go8eA{_GyWkP!{FHyxpB)@H62Sz++>b0#*ff~dEE`68^ z@*LYow&F1I3j!uSYz=>FYxBPO#E106ypX>%Y4|+ko(1pl#l@}07Bwi!l7<<}$ki|R zx|Z|s`&4v~de8eGyplY>8IUV=KS>?B+_im<7DvKv*OyFY%e9~|(hVuzbsxyXdI9xa z8K3w;i3I4UpnPL?@va%+#evR;*UnuO@L)+~53`XxbTMV3i}KT#@o(a)lOStbj3 ze>8B1_k{2GThmO^*^{*d{g-btKWB1Bw2LbyZm^v>B9yleQeN(5&LMJlQqpPHP!@nb zW8Q`OGbr=-nBEt+`ho^7ES2`vo-(vwsmR?|Ntl);pY)hc`0D?>a@r-!S0OWIpAZDyfO)3e?OAxAfZ}QH55xT4b9`o{S(r!%e?H+lwj_nboTpr# zzZG6VVj=dls=2JG(rrO^TvOR;7CezHme8uMJM>A(M*`qeYQ1kJErNKq5TlD!&w8$b za2yU|f`0YN1EX-2e|6a#NfFqqzbF$kbs{9DOSA=s&CWKL@+=|))VB+JX777EnX{cqFu~%uD3#Kn$V{WIfI+o;>2;#lvh)?EAf@z=fe0_r69)TC=Z0N+(}U13wqp%1b3 zkuPq)F%WRy*h^>J?7*JArL-bv6Gg6QihK|ahigy-aw%APWce@Gze44IT>r9bJ;xQr z(}tV^XW6|l{yFS{AZSSo3+$S)4gWWHU)#AP|DvWN)V@N`|NN0+q0NpOYmnU*oBu5E zr%Cg$Gx2)e0+qm=SQM6|W)#O6-D|2rEt!5Y?`jPEgx> ziU15v2O60_brDX--8BRICFbK>VHCteLl<J+2 z1XXBkZEx!5GA|O9#A|h;`mC7kez2BO46fv}&8hkjulfMF_3NW!RoE4mTLd_-nTQ_~ zVeZ})3TNZg{WPe9oWob*N3Z&ZZQnS=4DqhBR5$vc=1s}LZWq+!2j_mdhuZJr^^`66 zUX`V6Z+}xYF;8EpYOh0^xadusQ0P4S;Q(pknIJgJf8PE0N+43!M9FlKxve;>iweD3 z65#EDr>csXh@|8}M!8^SD{r0D_)4a!{y&RWujexDncZx;YUwDQmbuIb+(gl$PCT>s2s>?Q(D($;Voy+ei>@@ zI$5&-%2FXUz6deRB6vZ`RpNiUI-5)WTezPK+vFXA^`d^cpVO~Z_Y?p|bnLnW=$L08(mR!T4^t_f$*yM2NKp23zWbksfE{ zlZ|GAu-^X-DDmw{j0c}2}k}=XY&BisZZJhM0y0uEtPfx{tgis2HOxINP zX8EZ9(iRxL5xH|*^zZ*8(0z$$r_eUNf!gp@F^Ke3w;=lRzGxPq1-(rdgig)wy-1yJ ztHP-d8>Rm={?4)!v-3|&wwILNzj(IZeg9wBS29k0J3DP<|Crh5{%BlFN>v0Th_K?x zC%?Nq#!ZsU35t&-->c3o@E1e|#PJIx;N4)g`L0};{lQ2Ps%jdl8w?OA2fmu-mSCYI zG0_^Y_Ry4Zaj}eCWl5cjWE7BX4XuE}w(ud%5MT#gq`k77j3e7NsfzDu-g8-_+YK!M zvX%S0?FmMk{;qB(&aG#kIVy~{)qYCuk>uqUL9tS~WD#K&E~j3yPwGGcSmaCK7=n!w zSWFGKQ1t_G?XDswn1N}tV#fVMe5ECym4Fred$PUUO}FSnAZtk#h@C;>eq|tPC-SQS zDk-@ae|v{Rzp~F^ArC~F5mJP_azZ*R#+gv~o)d3C%}Qj(5lYLk z0EkHeC$)j_RQNP!g8IJI;7T!V=V93&VKYnfIC$$qYR0lZ+I6c&_`9@LQpJqt%CRAk zGHCNB+3|oGZ2h{5@1Sgcof+x~>!I|$+Hr-^96J7b^n-bCZ&t{Yak?s?&c-4n<8oi) z^Kpgwg2rb8ioc&(Y+{Lbj@l!vZWIm@N|W$YCDe3~tFaWdNW#=4Cg$yrA!)J`!gIt| z>4Isu2#{&8P|ujKUI|V6-n}LvCig`{yrTpGc552(Vx zNMP98V^%y22zn?~9Jxl^+UczQ;j31sXa4wWGQxMVN1{CX3)7{LHmOejr`3DT@5%92 zQz}XBapJ}=*7v+eKs|F95^S2rPLFLvMZJcrU){|KgxG`*!{?vuH$2`O6Bd$aE|1q8 zWZC@=rx$Z>+o}C&1ym06SqX}bt5NmL?h;zguzn@Pz#yu2U-O1G?4niyhF}H@Y*9K9b*9T@hqp;-820bB%1I$v;MBCCevfueWUx;R62d-bnYEj_VZ*^X~P0Cc2x-7xa2 zHN@$t{mIMnTZLychi%y!WuanI41oRkH&;k9Q;h8Kyq)xyg-|LfX$SRasJJwpDxtxH zz`#4S>1wlO`!C_;qoTey#hNmgUXa6j*ChpHrC-ep&-E@xX~DvNUBKXV1A7y>5ef=B zQ(o>v?da5tZA_qg%zJ!La?caaTuwVeu2O1H9eClZETE)+S!*lcHM-c}%#*O?|3r^7 zf}F*Ok6wDsmw}PAVIj9G+dk!^0j3|0N4Ltc+h_d5MTJ}^7pf{b@K%b_wQ}uu~`a>oS8tgR{N>6zw?~_Iq7ym)SsQP+!Bsl{_jY{Bl~(u z9FyFxcnVR|-RFYTR{Yl~4a8b3Ti~3MM8OAL(Jby^cV8nt;2&FGKf8@WEmk*Dy_`(^ zOFEUFw}+}de7q+ay%A#v+LX|*BBnt`X$?2-0vd1&ZAgQxl@Goiy5XE|kUAQrKM#y=EBMqUBvggW3M#WT7FZAF9CEtI!)hW% zFJ_~IWMZ#^LXV;u@okPKKR#+HCrh~1-am(AmFcEU@Hn2(>1`?f&`L~F?<<ELrE?dh26^ z!J>EST~24+PM308cdgt8-8iSbL!_b_x^(d~!@QJ2j0b0JSmDz(p6&MwuAhRs-Val< z4pzk!I}TEim;c#xQWbujLD@Gj=(@F%ZC=)YyG@pOwVI}?-6@Dl;q7nWrXt4!+YwLK zF=p=eq3o(bWek(KtJ(s~?DI>Oa(S(O}F`)1t zUn1}RP(d2B!2ea`^XC90z`xH3iz^m#Ddo5`a5j;y&`^ZSe2mAs7V8Vs zf$HPg{e(S=&*ac?*|SWBNJmjl1A|VYH+1domD0TY@X_^JR672d&jQ|CJc_U;HyHzo zeqGH$15XP$)T5a8-TIFAR?1w>$i*M|20t1Z@2s#A8MqiHd&-#fIL)RRTz zU>mV6c`~F^@1Y4kr`_gtP+*Cu(FOc3wh;OF93(hDDfo_)uEo_MKUQqt{LCQ%;J)Yq*)IPop2 zwRB_}Wb{8bCI09aF3}XEE=^&M>6^Vz+tK;BUk(rO&n>7@yx&_;lP3lJa;z3Nwp{o= z|8$To@{tK@k&i?^W*M9{XVF?G^yhoyeulHlQI%d_wfSUDSea$sQ21D}``NqS(x=UP z6}F1K@NxJqJJRirK7I{ENxeRM>;y5Lcrbjg({V}Pa_M1CYxZBuQ)Fk4qX@8nIb!j` zTYom3eBC0nc2J0^`#_|LmmF@u`;vS(1*^G~nAQ0{C9=V=No`=_Q z6L?I)RGt!0O`E~wjU+Rf==W;&%J@XY3D7fpgwq#4;pX!8!nKTV6{cU27Kib5UFynD zd>q$F4PiM#8?qJ~Z(O`kVcoc8#=fdRd&0N3>l!b7!|$JjqsaHSM1#F=YLA|s4(^zD zlL;ay;NlwfjC(aY-d7>fYs0G?!Grywv@4aC+}BX7Q1_4`F#PI!0r})vu5m$FQLu}w zqL(|7Yh(BoN`F#JIwWEBd8%!{j+Hz5j%o>Z3a+$FTkf%NZjq$gc>JmAHPcLAm?`m0 zbkj-C6rRuaP!auxTdJ|I>s0SB zfqJ9O2&rfKLQP|)&j6rNJIIwNMZtMVxxq~)$2D5PqKfqqc37KvkW)L6xQDz@(WmYDzC4rpTPD+_8KT>VNqPI?hsYMEEo?YoE9no89% zuGVG(5DNpb2R=EfJ+|LCupv}Xd#^^$gS{(jP+aZ0ir>my;ie%#JBGRU^W_K*Gbf49 zF`V@^RA##Mf0|9#gJ`tK|7k2KBAP30o0?8BT0{#nhe7R0n{eGVthmtGFY8tEc?`8G&$(@3Tu(1ulx6z*U zRvebKUMm)V=-jKKy1(n(3q&&}0ifewog)(byUr1_nTYTBC%TovQ}q>whk2Wn=HQ@m&XfGxtvhu-zWNBQ9-FC$-KuP0?jkA8sFYHW;;WJgC9#?nJ4Be(J9HpWmwqqnMdU^L!Bd`?)$MRN)0@=0eT!! zNueU5s;rZ~iL0z$>W{cm|fvTYk zkC16&y!@|5fg?`2WKa-KVQIbMsHxDs`K4uD%PoP8*A2uLP3+s#W(%9AR4XZ*;5_E; zh4V08*Hp~NKY_FIU%)9-!UQ%U`mmXtFm;D%)zW$@4K>aD1n4!WPIYWEc02^$+iNqi|%HAHh`b>;nFOlUv)NE*|~^`~{dlZH>h3Dzg6?+4TQv zPyb~=hdW_x@tg><2lE2(B?fIX+bt0;1&}t`j!-4az1lF%T&O>cx1Ug~>=S6Ua;gF! z&!f=>V2~KOn7=StxVrg)9ebX@-==jvp5Do*r!hwYy4ZWdCaZt6%Ti1%J7zZ^1zQ&< zM2B0{R5{hD8h&(>W~0hxsqcyBo*fjekCDz*{`eqL;O+FmJz*&R@#wwSTDq z`AclQoO%FKA!E}qTjvN%$bg9Ux@|XUC|)+s*bb(=L4A<(@ zKHc(Q=Adn;*eobj{crRW+^hgJYP=6nO4UzmcO`JoNeY_(#r|dtc-U)0o4F{4EI`fdC3jE6Q7%Opmwum$hJ9wk5X|jz@!S@Z|W_^o1 z>#yze9!gGoE|+qi40>tpq?$49@_t5}afoddxmn#MHW5-`+oi&d(Rm%!qt}4i)|Tp2cS` zWMVf5=n{K34e6J6h-jpGzudb|D^-i}Un~)7iKoGK>BW=hi{mCcJ-jnd->omyY}UAz zYqGJ!Z({c9`VGt4%b#$DoH_P<5U z?-2qoRgG;8xo4e0L#(^$;E~8>@w^-D@717tXgznc6b#8YZzt{P{UYzav5}*Av8e9N zV={Pj=jON{$6p1D}3XOEn}?VN(zLc7s*gUj?74 zX~rhKkjFYLrqnJ&+lIuR71h*GJ!^G$O%xE;6OXZ#R4MPfe2U(GR^K-PRKZO2AzPjD zQ3a4o8&p8&kRSiv3m=C@*@`E{m?%b7CEAjHf7)zH;(zaSt*I~Wb1Oipvc0z-ZLzTh zYpemEhg}SQ{1jOXa^Tomr6t2(6|mDRDg zM&5M&C{1k$oD`+G^L3sLkMjM!ERN2CasQVm1A*&KKmYP%paA9IW2}MY{R|;KX=pS6 z%?H_15Q*aZJWZdDUq+^~&R&S>U8c~jse;;*BQ4=3%Dxg9%P3o382KjFrV>bE8tObi z89+dHb_g3p*YO;i(1uFhvLxR>KQGA8ZNwTx*%x}=Y~i*j%~`VsaruL>5}CSso=veW z>2;eA^Es;mw#SEAQOJXvM zhF&r1xBRqv^nyaZQz(I zj2m4el3u7wCFd>t24!QI@!k4rh2V0{?Ueo)fEfIkn0Wd5tkaxVs_tAxzqI$Ti%I;* zd}QGZ-U4ncTuff%owvrM6Ixqnlv8Ik^n5PpyTHr)b6_^U8b^1l@ z@gS-vT|I??VRc8Wut!4D}~ePujAHxhl9>ZaT`~srRpsEi8#QU z=v8mm8~4_iBND$xw(zB&6!p)*xLGf|7K~F)Bi#Pxt8MPsmI|?qdl-$Eji~wmmgMkw zID%^C7yFdE3p9_1x@x^h(2x;3xLv&^=DQ^d-g)Yv3r2Q9@)XX6{;b~`;HMiX=sg<^ zD^|3IH^eQ}D$#wyH-~421xdxvg3Nxk=p?+UZ_l2KG}gTNSpjqe@qjCDlM3gJRYHyW zasY|R+$m7A4Y&|nzIpOZhuYP7;6$Wl&CjL_xoTG9QWr39JLL`feEQQ-A-W~lH$L#S z^SrvHNcnDC&a+!u`)VhI_aq^`;YDq7h2>BUNzH`!h%XohhiMLl8pYC@(t8)c4P~6r zpVHG>$9eRLUA>E-P{)_JX~6n}`Gi?DSIUc$s|GG5KAF9ddV8ib235`U+Nx*7!ga-E*UG<8mtEBRNVoip#tXpWdv$0BMjjn+Qan$e+X&KE)K z`Kui9HK&JeYU0P_rkG6sW!)*aG{2yV--$|1wM@@}MeQ&G5lB&(6T|&)ynIuHu(!zJHYN<>Ggo8Z~=@`>H$%S6z z)uQ&_gkk0oOVc%X0{-7>6!{3-hHH@mn=d?R!X%zXEV|o-0;quBBBTOZMcz3cYLQlH zDZm7THQ-n7%S*dNHJWsgjM#1qLpiFO)yf4`^1Yn0Mvyc_>I>#*1 zvAmzIpw@4@8;KxiyS*Xfs$DrBFS4M`o(iyWSM5yk;7${p*Cc!ONLOX&k0YTmJV)qZF+#2a!8awcu9S9ppG)Nb znsD_NG0aDu%@&EmI(r?=jvh&ynsj}!2UjJ)&e6IWJ2kAmL8B9W0} z5p%wOO0Q4=2V#4dB)ZCQ^g*9J~4M}9le5JvO<-;K8{n#+Jmwib7nUy)1(wAK21 z5Buu$Urzy!ZVY@x1fGbP`a$*Alll9uR~uY7XZH>XVCzqToqg+VMVpZGT@tfD%{5iw z`%&I$E;<4tVOzo{4YG^vyvgrz&=N{$R-W80tg?eytc)(p&&Dp&c}q__J@O0W72>l# zdQ9OI&G-H-6FVR>no@Zmfig?$BPtw}mlrV5d@BEcGqYT0o2)Dsgp^G8G*!*^gd9Zy zAt8X@JI~|PBL|U+!#53cs~*Nt&~wTXAj$rB8uzo`3e;(EkU7KyxMPHzPRMJJ+W9K~2_X3u zc>v@vuba#!wa_m6a$otLa_c2B8X5KNHWc>Xa=gj?K&|#ua?zdIrhP<(>&BtFx+bL6 zd*{LVvpP&k8JZaOkF-H@%9Y5$G=!w6M5L(TU=2nQmg)#qmWW)I`)5Vk(!;Xpe&CFV z#}*TQL`aOiPiZ8507myoX)!<4n@;b*p77$)o}19vVHZPlQh(07rZ!E@1UhJ(iL_7U z3Ke+FTBtsYPhLqw8eX(|O2baBtlf6Yl&?tRMF2DzEQ#(HEGb&CD`w3=w;b(eVwx}1 zvK6iRYZ8K90Tl`?9qjKsH$gS$y}iVkS5z+m^ln0P8i|)a_y$@Ac~jXlk~GL83(EGL*n*}&`&EqC2^WrgoZrSOV>%o6v#nGm=rWvL+n1H*-EX6IH;+$A14L}kL_J}npV9pO`ll%7Mpg6USObsW8ifA zMW|zACKm$L+qBRxlZWbd@Pr32xTsd$xWN|~v>lyAw{tnXqN7C$9Jt_fTM6|$If}vj zWRGNn#InAtQg2Z@NlR)D>i4CzocC$K<;V#i5vYm)GLeoHz*cdilKj+CAOmI$ z{#o#)`N{Cl1(dl{4_NQn=CpiEvjs&QzW~)M%$LFUoI0MVs32#ADdn}oC6mCi(9M-x z!Y11ssMl2Je(GK_r=G25AeOCvhXLnfa9zmk>DYBv#(Or98Sbt^$xc<%Oe(*Dc#E@= z@rrnaX4u_Uw*26Y9qm0CPrqmogTN1z4iD{^{GS)vwuxq_sQTqUFW2_gQKptJY=F-7 z@edsif;K~3lW_?8uf1_q?e#xZY#K0iBw*khdwyskx1JN~3^E#=Gh@4GTpD?Xdm_Zm zeqbtMCd?j!<$vCQcyi5>%D+pMNqR9%e7&ZKJSDjc|Ecc~=)O}D$`E*7SO$4JMDw^U z26uPDH9<5nTa&_06S{P!&N6=lNr4YAyDA~(2@Ew1glwDY=*?PmM4hYQ;2Rj{C)Mwh z9~>IC4Fnm^+w% zA4dsE-gQX(#lK%>^c&9bpDbaf{`tUF?Cu{|q-EFQJz*sSZwB@^i}0;Adix7|gIKT_ z?p}NL%`d2wc6o}rT)#vEuUhFA)^zR4@t)i{d+c8b|DZS{8pb~yzBVzHKWHw%_xm4C z9|p>+Kd=w~-nTy-zsC=rqWyt?kGRTYBRP&Wz2{FmBLqdkilD2G1+*S(2rSDMB6w{O z+_*Y}pW?yuQQ7-o&J&ZvQ5xU7q1VfiGwOK;!0zvb0{+uVS~uIus9T2~{G%eKlS ze!hmfEH*Xm_AQkLYu<3tjh!C7-OTirP$Y9g^W$dh!Ho0qG7Ck__mR&;ZJv4B2v=lO zyJWDx`^KL}F0I{YSp=&&zm&=hS1IM230ztkfX_4ZuEWUpq~-Yxl#8w>3QIT~)2?=2 zyOyZVisO!oB#it#ymHp7dKr6eYq#L0xc12^Um0xFwb?B!8L6Q8(z_dh(9kGQI$t6B z{9|Q+yg~WF;gW4KFT6OMuS3LR)w}|f0=uAAcM0IJ&Yr27yF7MsMG%>Ud5ek)GU7%N zNN_0;$lpRH>w;t9Pb9vQwxIqh`8X`B-Htx;+9wU72W)eG#Cu_fD?$Vguo4^VIk%nn zIk1Zrsn%!$p(zs`wnBgp0sRoLrr&ez?QwR@eg^;cTTU|0p2mWMlbMkCSzOMNGeO0Y z!nLife$PwmlysK)k8HU&>)`3nDXD939h*g<_AeYu%2E=S=Xp2sb*aP1pmo;)rzc0? zv%Xdq(X0vY0!cW2CFntd)j}G-ZPO;9)W|T$I#;*HiQfMq?Jc9?+On?U!U+Tm?v_A+ z;10nxApwF0hu|)SyM$0dLkRBf?phEmxVr~;r?8?v>fYP^cHi!IjQ4rIKMWXE#W`p1 zz2=&8uC;f`ek&=ioJTk*CobVd1@JWgyf07xq|>u2rCPoo%Qp_xA$J>N*#pT2^(Lx* z(V2)x1W<^U?8etB-%ws?$Tb$c@UMVE2_$v9l0IS}((o-04mqv~cq|u`y--A$tn_B( zEDHdKYQ0EFRuB}tLepz?(=Rh(L0UC)9+1v9U<`E@I43t>`xJ|IcFC_#l8pqoVBAgw zTxVRizfza((tk=~y*Mcq#;^>DtzH#Tci;PgE2Em1ycBkzRXsKKO%>5ZRbMpW<};Rh zny8VS z`^hRq=sZYI9;VwEJJw^lerpW1K9W%1M_0Y09y^LXYJwsc_(==<6txvNdNZ463LQA~ zdy>TWIt{ySPX#kCV2vpZISOSQ71pd_LH2!+PgdC1#9YQ+59s>+f?By`Csy^PHI}pC z1mleRVz#<5!@RyUXZiztU#PUYheh9(rG97};H7}{ScahI2ERn16Sh`GJC84)9jGcg zl=6wxoKdW?&TV#OM`&@c2Dr(Ua8|) z)NFO45tB#PiGrC?Fm{799pDu1sZP{f?DjLW$cvw~vnT+L^`wPCg{ygB{nVyzr`-8< z6P0%HC39~kl0gwtfUIPM(p!Gp-GyncDA$4Kz~3&@>0k@-6avCNlotV3-HeG@0vHvN z2b#|#r~v6JDL_ifWfS&~B~FsLqP+FTQU1gyIss0-IGURIuw%7ONBa_2fdBe#o7dCY zY5g{^wh=UvxJCaXVSrft!3S!9x+?pR*x`5sW8LUMofSHw^rX9C=5P=!B`1kjn53t)9uam{H&|fPh8V3?vM34zv3efiJ z3;|mQr4kr(1%{#PnB9KIz_Mz0Ms$?tLo;>Ae4Irm+VIiz*1D1hRf_`oC@BHSXXW*n z=02^&03_i_#^kX!A3ex^xBv@Q!-%(&TI!yGQ}&o(uMbq~u4DV)XIYOAy<#u^&&0#+ zBA;&O&Qk4tbUy9z9oi&E5KhV-=e47Kiffj#D@dLFyio3<1|)uRDWsoIBF3rj+i`w| znHHb_LCuijv7I{C80}{PgQVqG=-Nr87zdp<8t+p0k8*Ce{9{%Y!|f-b zCv{VK@3@3}C6F>Y=H$f-{DzGGqOdr~J~*WQz&-1b6dLkrJ6 z^()q0_OANN2)HC9uE`zNrAkrLjbFWeHyv3Tg`o{04-`?C@jEBc1+zW zD7AZqrK~Jk zKAf^w^k>Kzt+N!hcxK^lH1NL_b_Q*?8CFM*fgy{YLCxnAsFdaXTlE5duRjybB!J%w z@}}fS`J7e)U#3Iz$|R=BWoSPaBr_xg)^NmN+>_qesqnLwA>TBYwmd&yoHjy41Ou#i z9;m8s%p-d3RMP@T|E%F?Bm>o0Rj%LlR5UJkhp zcw6X)l#SSdo#Q?CKKR+Zav?KYj@@_wTBpW|krh({Ht2k)Axh%_yV+AjeaI^kdLboN1`uv0KMD2{4(j+4sCu^>H4!yZFV;r~=nYGt$9+P8LQak9|EoaU z4Nw0}6WLxwI%T!WDKrw>+k#5!q?0k(fbCU(E( zbE3H-a~0Vt=Y+1;EH6#o#)u16MIx=*yPajwdZtUdbd7#_&yiGqB?i^X5aQ2X89s4l zbu|-Nqq3OvTls3S%|V+Px#?We8cZYQ(9Q9bEJY-!?z=IE58e5&b}Jm+9bi zRctypXR%kehaU07SXsZ^{>*ppDsn6pdz{%3RJ$&mLP2wJU9)F;A+~CgG(VaqQ1NP# z{a9ih+12D^Bl%L#H(FLo9wv^QZ#DSaoVIhTozH8bn0 zuC~M7FTc3{y7^q#*kHoZKF8I@<>Is84j=1Xx^7$!4mib?RRxgQ){EI<%?`Ujh0asN zQszeNMNrz$R0TYOW?5cBAj#0FK?Z$f)FQ4**+&)5vKd^o1k-KUh>lsoFC)pZ| zxC$I8o^n$@3Q_NvP88t}L`t6x(;?|R=Jn>wXRjyLOl~*dN`H5{OlY|RTTH|xG9UBQ zS6q&pAEBN`TG(3f^Bxr0Q5nvhDAhBfzhH_$hv{4JlADJ&kAPIXuXVhR(4NvEN`@}d zwg`LZSroI>yTEjoG!62F25#5xY8Mx&x{nwnoNs$>k6gB0eIFYU5PoV$l>g$zhsoft z$7+?q>U8^+r)L z-en-<$^P!<8rCBL^9B9i*zZw_;^$J-y_tsLbnw%b*Qu=}9McVjAw=(6j#iA-FNqB)_e%O({dODc84*@(?)=i6tG@yq ztZyfr*Y`=Mdr^?Z!IF3T(uY$a2c@Bb-8lZ)7X8lEUeO}fbwXrZUMFyZt$LH>1?}@- z0KiqV0wLZMg;LSg!QreGxn|Pvz2Ca|`b8jnin*v78%jh7J;x3T!#z(fL>z$;JG0rtD&^F;1)r|5LuNCJGbCqI%AO92iGL4tzq`2+2idQ-vU@%2! zk(+r;k7tGnl!ND%5QA9)F2T^&XUa{kyRfxRlxsHqE_f=mKVtCtAiB{SZ5~1$d$hf; z5@2uj)nVWhEL)-Py7E-|*eX}fLkA)Evc1>9Ke5?mrgC8JC=icXkpy({6JNs2wo|2P z+2d8GgxmVpHmf5RW@7)~-?*m$&`i`wbsO1!V`~g_{O+|af!-}`9WwO@8~yA0T36yB zRYB3iy02R~HrB&Up1qynPyEhwXIiwUobNP&g!qnsC#<@NFPXn%zD0BiQ{s|wBv3w% zef=0>+j)zZ9r_7&rJ*!sWoV zN(VtVSD$9YAi@FsXl%Z6kY=bCEV;6k7#0xGc3VTGtXF6ri!?pbyhB%}wi(UOwfsoz zy%^Ztd4Eb_t$qpqwP{EPh+njD9(FW%NEV`aA9KWcL~aBdx%0LXHEH)TgT1;dG_HLb z^oTv@IgcY?VOhsqfwQf{>A2hwvzLsd=nLd-%eC5s+uggk+L*>(?P&PMgE6znql?^MXn~W z!)E4usZm-jg*+kcMsX%QVCK`5E`RGco*w%)Mf3{Z=o;vqV%VPsC% z^)@u*w%g+&73?0!*41UnG~{mTno+{D!g`+R$y!g)odN0zgP+UP%F{t0&HdZ>P|wTJ zlDdm1Q81bL>>0gwijas7TiL_wxk|8|sWHdVj$wEB0UE~u}+ z=nA|ZkVJkp=CXd-R=DF3>8oAiB$;8n{&Zy2u#;bK?Ke3sCdO{2s|38(aK> z(P!M>f!2Z5G#tP2OAe&Qo>0+DPgJSN^vrmA$+3b?y1}WLF%kQsHJSvfe-i-w1P3 zFpB)S7tK%e^U@vRL7jXuJicQsYj9Hv0$tX7`vu!04ml;>PYDqF8Ur1wGxsNt%2lku z_HBqmuX6Pbur*?QSWk82_?6ctP-4FH0_IYh(gWu}O;(|poGWr%(d>_ZO@{qNe1h`a zS${z=@kHJGzlS}6zt1yT>;KU+{ZDcwKhYk}MjyVSl-DKHrhkMc+arfgo0P&37szow zzdd1I=9+k@M5ROxwPN!3IX-|b$+`F(&bw)IkJ@Jm?vJE3`tebxiI+;X9$g}?E%#V+ z*KCjtXD_}|RCt?JK*lE|7R`YQ9X=09*DrXmnm8xkx^G;5eB|<0lZ)atdA*%ec;9Da z((J^Cum9DhtfD{sl8mq7aa!!kF!AlpmWWgdxYOC5l3|uZVMS~I zyYYvP*p7M|$r)lGF~locGv~2x8@u_f9DMqdgc6V;COCrJj#i3hR!En%48B-ghygg% zLB*7s=G4vSJiAF}pNHnX<8LOOt2Qgnb`jO#2F7!yt>iT+jX2>jVKf==#-@knmxMTa zJSqY=eZ7LJC1pJzcav$>SUJ9oP|8h2wL@h;(%fGZ?3OnYr#?^YJ%3x8k&mu8;DV(F ztT?If^J|&xwJ*H&Rs~-NgfRL@bbJ^8BszMAgzbWH_6%Ko881RlGO}KuWI9Bg&+6FV za{}Y>wroq6a?eY^_nnuz){0GA7ko@h6<(E>gOW3cMv6Q5MJb7@A<5a#rWSyubC?u< zO2D&AHLYc%2EoGW<^x{qE0|EPP@?J=eE;#wVPkG+6st>PyRT&)tTOR|6tjT@P+?jL z8zX(_6?G_DfJ)sRIBS-YT5ujK*GPD-L!MF{`$y) zyHF-BRB%P6iIQwM3h(JRKta4It?`LN? zmx<|`Jl-Ev#gvwX`WtcP!OPPZQ*c$D{)VzIl}HPiE+x5&{O^hlQ64)Q#hjrZT~ zt}w^HbWVX+R}%8-af9N_iV^P|+6eKtBZLdv1Xnls`Pa!^#6EfJY7kum|Dp~-fFE%j z;?im=vU$fB47_o@*Q0lK$FZ^0=%MTWVGMy^*p@sQ&77{XCMu5P^WMi0X zr%3tJpt4D8YV|a*)Pd%x6JXOc09yJ7$r1QBk|Rq8SgxD@@y2XhzyiP{K>ox+KJ;5< z#K6&*7m1ZI3u|exb{!V&@AA6@xJDy*&w*lT#6Wn>eYTWir>*Qal3&;Ph~&sKYXstj&nBi{Qbrfa%`Bq(&Dxa zTW6tyXwt1Co+Kztd_o5lVAj<;-+V>KL{wR6He43kBHbz@MfMv56E8XdrxF@2_MR^0 zA7xf;&KJ{1x^_~c?XGIp>9p|6gsNZ%r2@g3*BCznZ6#YDKgu>}V>lG#|e z9QH7;l?2@nZ!fxl(llIHY`#G;w6STpm`_5`*>6}7BVwc)wF*koT?hzcV~q=3o|YSw zT~YN!)9bp*=IEy5eOgW#)@!yDX;R+8W-G*Ckp6SF84?1;qwGyh4|vztS0lJF#s_p5 zNMxZ(w9++R?DhM_k16~ua|CIQpo|SZLW@Z1gxzHMF6b)WlD=H>Hu8(!%l4I{4TX>$ zA0gV@V%L$Nv~;w*he{v*{N)V28B(S~o+C4Q{Yn?+2Re0%{L3TRzCQU#6o6S|q?`)k z_bdd;%CA3u_*(>#6EX5<-%-ikNbtJm^rU>JvJv{Usit*qYgp6}lO6LFu<#B*^9Yr0y za7(Cv=m$BukC5F(Tw>j@CW5#`t5zcT?9x7UahTiH5PMU-T!BSH<3=c4qsE?kTZBQ+ z7`;7%4Wm5WV)$H(%o`+HI-A@goy6+}82`!Q~h(*V`CzdiO#!%@3;GZt}*1NSdq z@;hBa{Z1#c!;3W+_TL5_X+~_ua=8_;8H*Ty5;Sjy?(JFKdAS;_z6eV(Shf>&V2wPk z)67q1nu2}TI2q6No{=A+&K6&dO0SBec)}+NF!b9$N;A27>7YM?c|j_q2nXw@weNRv zk4UWe{L1P-%r{yWfj`XSVX5Beesg7k`suNRQ9h25qV*$3$l8szW`*x>miWsgk$^ib zJTIiLSD9G4y5XmD_$HVT{SOPR8+p1M4pSt?lTm%wJ-!>M4s!5{?LCJ)24Z$TXCuF; z&(gBHz+|(+A8mP{q*=+Q+~q!^K3i7ta}OJ*7h~mdh_jI4hZP^S@|iLpITHnUj78oB zf##2AIFA?jjcECa2_3Jy+bfb#&_7wzNP27j#b7Xs>nEGeeBj%+?Rb+Vc-aJS-eUU? z3q$1SXXU?T^G-&N2DR8b+$9h#27EsV-+OixOHykJv7?6GrNAx_TLs2nI)0WcNauyM zEW#N%ulyg+J$=C@H)S00dEL%2AorQ^Zv};Oc!i}}Z@{y@6ZO5<^gDV1l)chMyR;TX z{l^h$@K4gm2>h==TS1Kt=3NLKWonG#bWEu`L~)U>aTW zKl~ul3K*9SQ-V)Tt#u$1`o*<|Mvp$XDE6{IHce}bX`oR`Cs`;vnJ1GX-zR_gj266C zeJ2rqjm)yZ`|P!NNxo^J6`_5a0`LLDfjj3{5PY^ln4tMQXLPrxyvbrS3oj2Bd8eqG z5Xqg-%OloO3oK$UD_ZE`M|CvNB&||%Mnq6NoM>5V0YhJS$icfc9RnWM0zld%RXlP7 zzR2Jm0_A^F%^1eNEwc^?B$5RFn{L9Kdb7EqeT&oqAozwp&8@9;Fz!u1QQ`Hi~!(;z*rRfv*g(#T}0) z9u%Tgoq7$UA{+mW)6v<<*1zMqb;*(s;RZVrv1xdqYlCrlZXK19O&^HC41m;L&m)MI zDlzgQzgh}FZtTad8HCPj+Qy~k>T4X?LS_xY!-k-j){h6tnWhMMQ>Y`+8;QLD&@1Ay zfjG?iJ%WM3ndRS&HC-O3mM-H8oxVnj6g#4|PjmNEd$}l_`O|iax7xCt5I(*{O&GJT zaco^{6I3GH;rWy$m{|^M7i! zZEb6Wj5Blba|?=vwWB@;e;D7ynMPb3ZSm8TrwzYEerm<4VoM|2=$qK8I}jqYSP?Vi z<4z-&;$V}#8-k)n;R8}vx2dnlF%*}|cmr2QmIO<+ z?D{chvVC2;-oPftVMxL{n>-l4_#mP1OOf_jCNV0M-l-s16&s6AMptB6X{;a2Mf{@& zE4XX$jk#KZ5#Q&5{>-rMSj#6Oe>`>np4G@W+Pr7R%C?*$FAVcBQ-w-GpYA z?JGVek3p+jfqDCf4a*8*0YnMOjC6ve@m*F)dENSweSIJs3%FI|Td^@_@;F-9rjE_l zgV9o#0W%hDHjq*`^)@};UWafc2Fp%aGO1f~Xv}2qe&UnFId3gL;H-4l$vQr-%X)h<6tYS~V9Z)`*HLnoHcEh(1YC~)L`50(he z#H6Rb`NgrE;J~C2_7oX6%p}xJR;>0nOWnv?A^fh`$R_!6r5cQJiN(yqeHSNy#k@Y2 z4N{L`ehQ_*=d3NbrkEI&DZ+zhvV#3%?E8-cmsKU)S`w zTZB9u*$FNu*n2hu?p*59z#OpRdQ|^8J%OQz@yyXp_~UVX51hoD+fNqJFvi+aW{R1%6yGSn4ltL&KyEkQ{ zh*F@X=X-Rq+2{Z-PQwyMRUFnN_Z7|IK!_SG2bnNlkF}1_G4H&a5MYXbnFPM&@r?V_f;0GNU-a$#XtPB zn;8e$pPutf5h%`lkG9Ajb|GP-r1RPE6nUY%eOc!Jpbd}7IKB-9^GfuBSt6{v{E7H> zW!jz3^dw4!k}_Mn(4^bK6AiXUq@<$RsId1Fy=ekLz)S>5;>hIK=mOX49bzUwT@htn$g&5z2m@xuz zI^|~+v=VYd+48ZT%P)5jkLd#x#hcu%&usy|!q~haFPe_qOu)BYCwXbk!GM;LguA0DGC9ridB|q;S*YjT|8F}u%cGJXr z)L7BA>K*FHCq;S*DUu(N{Kr)+SFGHI^gp?38d!#7*--GL;oiwGUf+a3zXYn*yQC-e zNWhcr>MB6GW(#)E=Eq?#v^)6l<3mWb z7sPQnzBkahVBMF+=uz zedHt7Y2ZZfy~?+9>xobM>1f5G*GlQf5f-6Fv(ehRIn5B0!@~n;{N)x=fzt-1aXdP} z`ft+ch~hUq4%s-~NDODkr}?=7P3&(O88xX|uW{JaNQR)Ar?HjC4_^RhBU0*d=f z5#M8?DafmC{-z$B!FM>0R@AN8QQ0aNZK+mKjFX}~|Ii|iNUDhc+5S1L_HQO?S?-^= zWF|38OxJ(?%a?z?!6Ou}Go^7%|3nbrfSDxl+4YsH+kDsD9(C~rTJNs4c~c@ALOa#v z5rgf4+K5Atdx*<1#b(CVE*c`c*2evr>v@2+qj!C)(9%0jM5rBfa_-jp95OWhPtj_w!cAFpnwV@rJGGc;YdT?3N}?ZEx0hy)4-8mT z!uYwNOv2jlG=C{GvR5MzX}(K_h~D^ zJ(Q+qC*yLzAC0S%QkkCXPpEbweH7nkCbU~wIT60U4)%johwu1j&u6#;OSX7K;6>X3 zuAh`&9s>@@@DKFX0{ySi`+jvWecx7ms9!8(xsJ_ckI)}}$Wg*;%37)fj~%IHgpd+K zTM;B|-iI(vvSKLEep@Y0`6i?}@0LYunRiOeuM9HTOE#6O_^pETH{M7){j~i`k-occ z@8dK|H#{;Jc9R7MO0|c3s(OPc*P@X(YD&D!U?Jg{0)3||Z`sSmO*Q%sKCwrz{$X|9 z1~(ogpQ98KyXp$C39?bt7rj*Xx^lItjbM3i{s2C$cJ%BZ9_FTIjz@pPbF(cwqVQ|| zB%1Q*XYdhi2*BaF?6M`cd@#)a&NNySbZ8kCSVw(L_b)bHEjXub%XK(mL0nzZLAK1{ z>Q*5_Cl$Jl%QQer`X<5yN4(6-H4V@C9sK(-EFY7|KLFS6a>A&^*E{WU>f^{^>OuVS zwq^FtI8J5o&AiU*_&5P}(NaZE%USlpuSiSzaRG_K*q2WgoLAi6Y<5{?+oQNnPm2PO zqV?VBe!UJ6upUGm)>tQy@0`}KvT5;DU5NfoFYdUo9p z>CF#m29~tfkBRvpH!i+khEh)+;EF|J^;EHvb-KPIo%R^{bk?BCoC|Sgaf7wb|AF04+ zetk>0Z`~&bR}K^l+-2IOm$Hl1`5i3}HLKnB!E6F8QDmmjtv z>_h(&>uP`&EeFf)6F$$xJt2jP$w^X)f5j8jf7U7%@&1Pm;Agtus3}m($c)2p zIZ0P$qgwEfEZ~NO@*9k^Ama-j21rkS`2so40R0&J^AWGQCXu*TE;6=9j6d8|%UZ4v z34#kcS*AV7%ZEn4?_bR?G+pSpMYFCkIn3CsAAEw(_~XZNXf7q|ux2DSM;PYq-#ifr zOyZS=pS2_%)F=6_wPO9JW1r(%!_?bkqeYWyCE*`OK=7+FeZ{}&KpF$T^}jJX8EM{W zoH2GlWERuJ(2>kl$=sgBlK#h$+@i&h9UwV;5Pnm5b&vUm?vbUSwbZ0N3c8&bm0T7=2Z} znL{wR0`;Yo2B`q4L$ufDYUX@45W2)3+A;AzHJ`02jm>C{`4CT_YQ}QX{??RjKYU6B zlpf>HjbJwbj0gY~l!UKgd9T?PzfUxAjSNB+52}v#SDs0quJ`qqa%mFnTB|qH!4rA` z;be%MsB6tolqY&jGj!hY5dN5b3P~8^Ul=LdbPB$b8gz`%2DhOL#G&{{NjJMKz7a!o z<*~YhPf@EphSO2QPf1;500&TwAoI-W-*w+R^AwS0ye40CRC0{SqWvGJGM3SVMK!}i znDEAjpv4~x=vP#$Wi$Jlb#lG>x0jT~Z^Hzef0U7xxX8xX}f+1HepuRm>N;&`A@RB6;)J{2$#xpu8B_ar~JSK+2| ztKPe|YZRI}zQH^Pds+h$mVze^*eQ!JP_rLa8*iQ=u3oDzi$Yq#%{q}GR;<$Zmp?_x zgoa7J$wu=XFRZ@uRH8&eFr@wx#ee6P{W2M1Uqj5g=1o}i2b+_AWOFQ4whh?Ke)=Q} z@gJjxPsD_Jhf8-C9yJ|x>YCrZpm~hZqOg{d3HIDa`mT{d%}8E5tKBw{-rE5&iV>y3 zW>jTUkMhc`_oqi*z)~2*P44n+(Z{&J3GT*{CZY(I&pt-}MuWqmc=UfWgZ`t0NKoYa zf2q|K<@uL98y;fxUxA5j_sd-lWG(r{2Vz}N8e@Y4ldQchs?U2Cm{~a7RHW_$D8v2* zF<9}rwP##ER{vT`cmn{>BvKzp-fs6JxG3df**6#*)BD4GpTG*kwzRfxgMR3^B(pt} zL?2Uoj0-Bf=*^!lb53g-sXrBFgriIacI;k{X%6|wY$8@DKji?%sc+K@dxBsOzKS>D9yaQn$HKDQ7VI*hx==Y2ogT;wEu-{?dFD`~MKKdWM0H_gS z?czDaY3N+m)X2X3oaE?(4$_`$+6RaL85t*uHyPTeZ}MJ7BHl~%mkJ%jPfBKxfD4;L zU29f=+5bR?Vl5p)T^T_6d~hGr zXQ4bAR0HmJ_Nm)P%!vL9%_=>_R-06S`>5REoVpVZ&0(QQTrq&Z;>kJA9TrNyXbe6< zKGxCK%kxGjKX~){LAt4!%fVoONB?68>ry;NxuNC@n~XHkyt`kCpeNBvWO z(YG8AJm=vdXR3+tSCh_g3H6@>>G8?)LV3yjqUOA-p$FP*nigVR6q+HWR}TZ8Kuk5k zv&c#>gz_>&%AkDr+aI&lu*|pMg>rZ!c9&K%G7B;MsN!$JpMK`#&4tF~5)cwz1D%o8 zQ%dRv9bKXSwgWNsLx6P}&MC2@22oX1w)R6uZZ7BoMf9&CmiEyP1OSPRg-Zb{$4QLv z5T5>aaJ+h?SJTSBwm|<8b22iI%z#Oy+fn=2?ng@a#%w>`a@w#Z|K5zV^xZ&Bv?i?& zT1b(>zuRPKW1|0}#V(W^e_k!6cm}!Zndjt;HzY^6ch@fa{v6tQm|GT{xOA<3!7{iA zbv-vfyjiMO*TQ`J__0^cX8vv_C+htBnr_l}R6K3$rboY>vR41FWtjhTjXQD1IYkq5 zu*fZ+?%H1{sZf`jGceDVms~v(v7XB%rem?IEW!gZm%Y+VQLgHns)wzL0MDY`l9BOd zi@g|D^+VxbwKe-8HQAeOpLqP|51?70%QDvfi@F5;$)il}1XZFLKwg zWgf@AF*=xJEGOXy#R%Hf%q|%LoN1eX4+Jsf{)_qMIBY^I`zKOY|L>t44}-fYoWoZv z@!9^_kuJQ@$Gtr2>w%8dN^kO8VN3+mN0?G=-2LUQ@I{oaH zxjRUB#rLNr50|=4U)i_dOM))Kt;0YD75b3VnYbc=NnHH;n@^w zP?yPQ`R9n0tPb}AfC^%y9y0#R(X6i!pUqe9N`!%ci-+9pO+{v_)uBDq`))! zV;;1epMLGoDtYRzs~VXA{g?W%DdT_fDw0&^s3SYY<2xg{Dwpd6xFAj z>N=BTj(Xl9Ubhb48xoI;X<`?6G26O#LOrPw?jZ`-N_spaTr)!Kf^qPI)+2q30{wDY zYqDu{C|0ceZ)JY0{K);{e|$R9?gC*t2;!_G`cuY)3# z`~&3KU*nlf8>J*V4%u$K@H%WS1#&hM;>*uNjatIof zLhv*TdVE~)^l_@i{bqn4k0jnTn{r^W{0c8abT>VWJ{3 zXo}JB->5e3YZS-GY@RQl@OcgsbVwvlPbaHLu?Ycx?B>cn%6o_C-Y1k6E&H)h+$1$; zF^1#qu*KJZwoE=qKF{R-g^Er?`~2yXZ@VcXEnqPxI%8RRY|fPt>g_&#ufy8q zRu8JHyOP?gWscP{f{e9ojecmT$@-vkVc`kn3r9nI&ZOsEN|P_={g>5>CM!f>_D6Ag zYwl-K1+M`BI+YJ)0ya5WMJfn*(M4pHQbVtgQ5(inE@?4zy$f>(=*y37G9+>1muzy& zUH!mYAQ$%ImerEbm&3x9G+#jlwF!aFYF58u`RAC5Q+wmABck+)=QMeI+eKNGq|?<7 zSi912RlLZV2p`gJQ;WA`^p`Zicy_N~0-HG`NF$@BBZXeG=)J^~U2gd(vT8!r4+ol* ziGv>Mvp8R^!Qx**JLvBuK5e*X6QUJA=cc`N`;;#nKOyAKcYnXl5Vly6pgly`9|+pI938GzDFBbt&e~wr|C%007YaNZ>r-y z)ch``i_;d>1s8rL2@r3C87@NhG21>SWwp_%x#lHqLqt9a zS}6?Ib0)ol*_&m+d?C>W?mFZK*iNI#+ygkW{3aVNuJuhsYH0dY*GBBA5HVjD;$77C z&a~D&L~9I}J$InbEW5(DC))~RT%~L49MaN(|_A0DDgkTv<+wp%X7jI!~13!_kgOXTd;_At~dTZg#P>S`QVZ^@KQ*v0LW00Rc` z4A`}cNeA{)y}|c!7dO_5nc}K&hhT$xyX+G}bKfjp-=x?a?V9mEuj;ZVH_NsGADCPa z5@0u&1-JHMcsItG1T9BI_g!sw9|lTKR#?WWx(5n=`kE{SOHrL6)G^VO4 zoWtx$rNGP`6XDiJT-jc3!r+#b1%|3UQ^s>L!7S*%tJ26mOFA6oJL4}UX*YlZfGH~(I!)g9SqtT zh+F|>5~)t*IDf@=-n9)sDAx%~63ywXc)_AqZ?}f#2m;MhFn%f^41eP`za6qVy%R?` zoD!AfKHw$yohk7P8=FlN9UfjPjbaxr9^Qwi4s>5YAkZg&CUiVJyl#LhE*%|RC_)~M zw6rt<(mRRA*B+BX;2&@0K%u3h%OWwvkbHcR(=g9jkae2V+p=(PRyc@1eOJpE>G3BN z_^K`kLWCeNx6fE){M+#VA8~@1<75R4X^{R8_1XkHZ*g*k?YFLbU@KTNM8dUqb zhPX^wEIkI)(8y0bJQoHE6ie0L0w=nY&@^<$j@R|DHyC@*1)gl@7D3r6{rF^DeT!-t zc?Ia`_HeHw68Lh<&}Q&wg7#&?JPoW2_65XXDzIBvv82%umQszPE<6J$FlbHVol78); zCi~j`vVJes)Kj|%uw&LS@=ZWSHtA@daA|>i=GDEz#+abKsh?N>FRA*IP~PPZ+V2a4 ziJ{KGm8@TAUtF{de9SUksb2)`K`0j5inhY58O^TQMJweh+p)Pj$RP3mMBTQ)ofJ2M7S<5?I~?VQOGuk;D_8&Q&)s+d)o8o&sf<*Wg}R| z2S=bo>4r0eW?8!()&)MKT*?ovzjV}}`?LL;No)+v6_o}g2)72`w6Rnf7wQWras}98 zrD#$LW+*KZ)_FI)XFb4;&YmECoaA>2fi=x~zH^qpeo0ph-o5U4EuuA{2V1%&B;=hM z!&#a6!kgf_Lldw?yjoVhnc6>nQFwXN?zo_YVRVhvVRR{yNZyUON9R;j%a-UM23fww z9ok!r#n*v6F62~1)o-r#D=U=dmqJKWro(05rmQP+j>ag51j_U30T&7so3Ri8h_kE5T%OFN>Y-?&`%><>?$jEVgY zd?vUj5v_8(?$h&)DrCN}OyVUTK#i9vM_v6r#AopeN29~3rh%lp`=to_<;7bW7rViF-LvXNb3VCQ2cuZccO1rQ*j2!YN~sTO&Rr3@(r1`8O7=IO zfQO!kg5wm4L899U#%RW!O?meBz19Yga2~|QC3hj?>bIUJj5zbu8d_*sHJCu?eJfg> z&xaRYlxIT2f@z*Z_QfbCjaEwwWWV>4j_!7RRr;M5ezaaQZ=u**=GCLKRO#Z9i_vA< zedqSrfPv7Q@bVG9Kx9t5mfpd(=B43K$I(E9? za)ERF($k5O=Tlj+ip$B24xVgQKS7gLIlDz?snjSvu3@s?ORafD@ovS{i%0-<=xxpF z<>_#EFO+%s0T<7Q^e=GSv2d{$A=SohwEs{dMN5}e*YTA^=*8Uk*fO1Z2mLRg9fdF^ z^wjTMFD6EZf-A9u9%Jh%Qch?0UK7Jv@?D5vSgP%5akn){gUO*@t~w-LvZUgr#9tk0f9sw6o&;9L(=%;gmF1 znw&oBOq}3upD`o6#<(mtthwpjz-t~Zc8*YfU12|*`eR=e!kfr0>V{^xWbhNLg#jS@ z*}!u60qJ?i7%NL^Bc^jbd&CcXyboTVFvjz`99J6)?jlSn=BS;~Gusi2^v7C&Z{BgxbyzzXlMq*3#N5g7T@wUc4ITgX zu7%5?GvHUJ!l<$!9$qbX9*yl=J)APeM?@7anf!SZzpy_1oj|I-+||Hyj@=c-pJ4z} zRwsKE>#i9l>S~a(9WMd6NTx`LK47aEI)y6hWSzrSH{zcFB6>gXAB+j2+g~o1auYwz&IXN4*o&T0xVy~)4?6dS|Ei41mQ;~{W5g#m|0saG6aRHt7PZwXS z0W7|rpQE*YzkQXH>5CxWbd!Bo+M!pop$chid|)$>%r0SM=SKi+1&z!DoOL#?jz&+ z9|o%FtIrlsl)d&)#*$AN&woM&pRT~_>8pai+?K|O0LZswsC>rGQ5RHY0pe3~M^K#L zV}p%ds_n#(pAa#Ew8Z>7@;1>AM8AX3yS^^9D3tCx4ZM$o1=O1iWDcamzp;EQ0*a>o zj3=|wiH^=n^Dz_a44BKsA&D>9Pi8!*T-Sk}=>gDlItZEwu5tvZB#oTuWbFoVM|hu; zSLa0k0vDKH&#~eryH(`s8?zW7}uy_H!K8PBmpu$!M&Jyr^x6+F=VA z=lPAOXH!cdMbF4O9KFA0MVE%$<^EO1$K=UG*@HK=e1R=Eh zH>>#X0ADKBPA`QojkNNMO6zHSBaz%h0N_T4I>|sm5-Re=#o2zE(^k4}ABz+l4WeyQ z64`hOAC_@ZA>V&!+o!8)Qg_;;V~5G2{UwCR_K3yRa}nw2)OkOJC>{tkj^AI>R_U3G z?G}7}ch53FX+5;)$GB4cKx%ev|y*ig&-qU#ZpS~c%s(>Q&-;}Y%D zeOlDVrgtqw6BsA@yjf`ge~gjP3$v2(^W?JZ+hB0M?{<+#v}XO3{b%w4F-6ngMoVUt zQ$y`Wn!Uw8edQN9W6A&g-|&o9T!c#c11p1uqRRq^O+N>|$;L0}q zxd#xIDQs?%-1nA|WejqQx}V~c-MvKu1CXY)*7u^8UVI~W8hBBa^3s3`lV3-J38$WAS?c-5VD=&|EHR%aANZ_pqHbmQRJ8iylh-$_MKAe3E(0n(q zOBAuN7>XOOdY^lJK)^Mi1bBUd#6V&e!BTYC?GR-puC-Sxuug1-QC*o*>>PK>NNIT~5pmaac~3zELFQoz?Ji7A?JfFt zWu)ZfC_qx!M96r-@tTHGxxX?vMhpURzVi6qP86Ks^JBWTmy*}&F#5-A1YDZA-*pzE zt4()GM>DBoiCi5@93oj4E?;Z+yj_?aFZnQ7vN1B21cwbJHlVj}>zN{5P_4{!EUZ+xKZ>b-KrbJx{M13JC^xZ(Sb5Ot6 zjB$cTBf>lozBM&WFTq1i5~E3J=fyqG9ah|w!63(ev_9S~5!?c_5=Elo7zEgll1pQSF zxEr#l8!D8I++p z>({Si;n|`|FWLKhw%wP4z zueAV?MtJv%%6Ni0Y;v640hj4`wv_sTrU={juReU=zmB4>!b1u5rzsD>ZAyKzE|0~3 z5KmJ!AH0nnS)z+J#5}_#@irZ}>P$zPR1KID=NMecGW{Mxw+917nLY{zGU7#|o0fc@ zteq7FWvqzqkO5-8u<03%@70_o3egSpj*tihi7{{55M37;T>mnrNh_9_VYR$zuUBJD znGxXop zspi^Ul&)Sm{FADsPVy7+W0MQATmU5TM+H}wELMp29LZSc2EF@`Do6kF0cxAl$3LNh zE3oKoq&%DAnYXleOax8N)hU+yB<;+cxLJeCZR!g*9nDHFNtEg;Nbu?<&cd zz587D=Eg;@$MkrAvwK}P8{JawQB3h6UEo+hwe(sEr(L%<;MdZ7T)xKd@vDt}#n&K^ zwWnuwedDAaacMqjqP2y}a>k7Luc}Bt{X_{87U5hBZ_}nJ6z61NEhuEY{5c{&W0$&i z)yW6D1j)0gR3RrjQd6lpn?HFl)SAQc9L;jv6dhN0<6MSIWQb7-{Nqz%-A-qSgDJMO z(!sy`@`X!9BH?&TcK~pzz`4R4CgrU~wWyW)hUMgvcaAm-qs|2WJICK>b_4AE_|3U$ zLg70hHm~6+F_A3xHjV|3YzMNhsw0dw0&qW!&!}SUs?ZsSrg1Dr&{CBvb5!oAm^R>L zADEbo^mUzvc!btwKpeB5(H6!0Szuf__LeWfQe`?$_q)Z$>K)g>cG%xENWS@kL&X;xg;(KmmD%cu_VsrFsHdERn) zp>blfXOo&+?heGU>LaTVs|BGv&gT{Q0rFK2^8Q==J{xI{%9yY^5%gpaRF6$o6B%EqU$j@e-}~ zO!<`We=p>D0nGHAU0NVndiff0pJkd4RoOaAj5L56jx2-Dzw=4KyG)xVbyjHjSd8o#}Oc!Yf!NI zfzVF)`k0^2d-Sz7Lj+UjO}1;@plUO9p7T53PRkm~Ue9a4zk*8@v)XM01NutwFEC&8YHur^ zaIj^{73T6ifvKt#?37qHe()m@tUT^pugLiSA$7=6&@T?KWC;I?a z&ge29D=S=BU;Uatn~+*97YLGrv}9Fw5|V8Od8MAm8CT~%C>fx2EaYSXRo!9C)uNBn z;0e%lGxs;dXul6c$_WAfJ?q7)xV$roQfx0*lb4y8#yjjGQAfc7=r?Ge*8M37=J_g;#v%^>y? zBjylVhl{uQ2mN15i_=cjb$-b_BVJfkmR>rl&YdK>CsN=1a6}*o_PmN*EcYjl7VP-t zJ6@$JFL%=}yu+it!u#^oGw&vWr=d%FA=$#x?+9}CHr%l3KGW_YxL%46HM~a(1gb(h z#M-Ey*yy1;x+T;cb?#i}X@p0Dwf(_Hp52xA|iT>r^iiRqUQx0m}KG#{B7TMm?< zO!OMEPFEZ_Z=?pv`K4=ur|O^3GT@1|jFh!DX~Ji>d~q2HEvp|lCTzOE6FeftS%(r| z{Dz1C1m%y+{tj3Fd!ym+Dm^f1c(KyFYfw7>Zm)BY)rAC`>Vt{grM#6eV0HNGVA=Ep zm+#{^xh9_^-sVXw=*PpS^9caf-V(WK@tlCGzpP9Z{66YAF#5!nZdjv0yD+Tr{?CHp zZv&`^O3U*_;c%Wq;eXsHhO2NJrhm^f^7nzn?CR^!pvex_GNXKmSjBZGl6Mj!Cb|=d zyefrr6{M8Bj>(DLn>mgp-K>prHvpo(u_{IVAX7F+Dd2-R>J-J%OBBGyK8xR?AJ*`_ z9(y~7=B@w@FpIW}Bj?$t%HG6?^?!y#QOJkLO*thMRp(Urc&0B1Yp1I#$CU}B0xktC zaI28V!*^qN<_qaPzQ5XbN6*wNp38w#Caev?0|rArSV z0gn$!|CWs`H4SVXpk!DQ9AfttIxfJ z=8B=9$iXwKAA1ZyfxBNTmekNOpkqgh zuCFNrJEzFnr2Q)1g(J77bd|dzRX=I?u>@Uu{|0%~M5t~@m7@s}o9CNiFGz;myh=|ln%X}=t7l&uvs8y&{7o6()8T#R@>bXaW#nrA%&s#7`lYL-{TMpJU)1O zoz6;S`qcO%}QEtWWlplnjn`0Bn>JK{G9mW=GXu4X9qZZs1 zf3&`>0$sge5v7e~KgpqC@M_GY@Z3iFc@QMSAz%6I(^&rln1J)bApAhFS@!Q8M%>pozuX&r!oh^P}!X2l*j2`Lkm3@A#+U#4Ui(%ZoL`gqzvWDDTEmjKxNj+i|!~QnB_?GDPZ`kHl%77pk zdO~L-fx^=I$@RO|0*8!XvK3k=e(zbwwY}97*_4;<%gmc5%1H#N{R>6Bn5j{n z%1}gKY?@%6P;~F`mOzb%>b5QZtB|%O$={k;QasrcVeugkC*v#M5V&=elT4Pi{Q>&; zNyF69mXp7Ui7}NMcs-q;+yrm{YaNq#W#3kF{1lcqlMNS*C!wN1`Cq=7rQWgedk>Y z;jqkwAlb~nNlf}))JS;s^N~qIY-%WL?5B&x2sCQ;1WN>5_An5Atbuyg%}8T*-=5#V z`1HuKQH+bWWl4fbhZ4i#mC7B-6CMqS42vlJ4V~kbdwXsi0dWRA$b$D7!}hf>wH1W< z`($+$K20Ek?P7CU78t7UiYTE`v7h+XO<*w@*g@9z5U}vCTp+1LvWx-e>q_0E{A2O0 zv${zMyDx{pV|Reuz%QmMQQsK-A+snOG*obb@-SPTGgZQWgMV|K!xw+l{n;=(A#W^q zR+FvO@=+k{IzWz-R#*XQVB@I#1sN$|%kNvXSpE%oryybKm|mu|_(!Gbf+}a%fWe_F z?Kl2=uWal^&&#lJ^Eet0-=Kjg7{>9J!BA8lZ!V`1}g7__9Ct?eF z(2?6v07^i$zbuG%WpF02QEdEZlVt7xo3f%iijlQF@D zoK%rh%Na0(e^EP?!G%n8HpjlS_eunhCQUylT^~0FviBz)OYL^)=N_5@U z%NwS(Lg(stZiDcnjYz=uS<_?pxHZ0fmwpm&D<(bTJ*m6(9g zm#pm219oZT$$B)@;auaF#!d-ASJDDg>P{s-;4E}p50a`ytEUb*c^>?(rj@#~cr5$^ zT->B*=MpaztYw(OX?r~J@-a*usS&;!UD`bBI?Ju9o@g`n%8V*E{&~8D zgHIwXl~$1D$a8~Ze%U8C7py>TUvIZ9Lbr(05#GC#J8N(9?qU!=_akR2q1{pkIJm`0k<=Onbyvr*5pl-;=7|5jSpX+51}r zU=?B_Sy77|jUEajawtjE;s#KjnT3aHmjNuDrId)YQlLa`%zS_GSDvxKTFbcTxJYIzv7_-61OG6YE zx~Zo;#4!IM3G)dGu{p~Q!d##CGKx588kyKMApR);R&+AOA+n)EaV64EA|XS4LbW~! zLeHDtfT(5ez|Ps$qHpvbVhc;1e%Ov@$Yx1?y-rS}HCFJAstMm3l~t!R{Rkq38dVWD z(n_dWdn@$Zj|K~~;L!YR;z6~hoBC74{CyDcyP|asQmSz~_#aS90|XQR000O8hfd-^ zC`d05G7A9!-y#736951Jcx*3iWn^h#FKKOIXJs=kaBgSRx&?3?O_b+ZVkXP7m~D&6 zwwRfjY*CABk;Tkxk;Tl+WLeD27Be$5L#x#*f3veYb2E1_yB8OC7ttNrRZ-bh_3~xD zU;f_|1QASbG+hPYwFFlSFySUng6PTf~Jjh6kIUsEzNA1y&g_rg}2pg%B3OB&zj zS|n2nBl^13EiKSsfJ*m{@6W}Kj;C}>qH!D1bRM@_N6$Ry(r^0TUc5V6Y#XcgX2AR) z=oVOK8>sUgZoH@wMa{vKCUC2wd5%Qcc&P#Ou`h&aA;|Q{f#uIJ*tNE0y35lNUNE#|7D2kP+ z`BK6eB89ot+g`~QumJOkI-M>rHzEzB^Bp8)Ibgw??K8(0Zw5*Mr53Lo8wb~=-49gO z{W}sr?NgCwojE!&ygzDqj3<1Yf3m4**@wQ4w=eS_y)7wNLajI`%k^)|aD(*QdOF^` zb=dEJww#}_s^%|4({x@~xW1VSTkDZ;TRQg4I%yVl!iquA!sGW$>xuM&p@0q0{niGX z$Kq6^pIagUSR0J4NT?=QPI=9|wrF@(v6_2jamYqxeKG3ZGiy0(DZVZ^&t>4#vNaZn zSeqkHi4FW=O)w4)5Zpr2x22=rmnR+%$zw$9t+ zs$te9Y$eh$sM<;Lt>uyVphvpRuqC3Y%J12Q+fT6i_&5A9^j}xLr#UtI?$LU;e(i z8V*4qq<*)dcM)Jk#ZB&yUf0)iM_76uzjz-b?c8nDnvsUIW}0~B93gN4#m+>K6XK-P zQ%N;_?Q8Fn*}O8XLHUMBR!fQ@44KE0x@k9fvF~y1+WxqGDZ4*?XL)Ys)a~jpuyG;> z*D3;zDp*Ha;N#yjnHVkYQU@bvnP}F8mu_Fo5m=G>P3IU_R_D*A2Y-C}AgWV({pHd2 z9S&*#R>|nk3}2jRHj|#{RlK~?eO=)?(T?nT-kMJvH<3x(@s`Aq8POtR6w`O~^~s`& zC+!Gzni@QfhWgh@SM7pnq)C|Q64vWaHQ*<|U{R1FeAcgQ!`CI+j{P6U-t9Cm3h+CW z3`+1fe*5OoNuDcsEg*-4n45S{{Z7iq<|5)CC%I!W?`wJex6fni*t5y7Ga5x!{3`>K zMwRDC`&cFj1#tco3{RauJ`9FuJ`Otte; zdz~&iNi6?8>3`9zuNn2Xi$0gnJE?zqkaWCy`?n>))JM7O64`f`ocGBVDpceyG%u%;HI*m^RU^~#+Rl_n&^GD&DiI;RYU#a>pupl z-Kkdi1?W7)F}J63JYqFhBi({n@-A*a>z)Ij-WlMmEpO?aJ8m@Zp3l(`xz+BI37v8o zG})-XO8H7ZpUVi=D20Ou?1JJ5H}N17@&#S3m%roHa=EK{ofM)Crsf*Si4qdO+MioK zX;TN058hwS)J>@*MzjXG$Xy?)s@3nDAABrNGpBhqg2K`VVxM?h`R8GKp&%k>kdNm$ zRMP)Z;==r^{b^7yuZHZ2Y(&zJA3r_m8>~N7YSeAFeYswGzi=SO?Do8b6Y~bEt%%m- zp`B^*!md96bn{u?B`-^j1K&fb#xj1}!BBhUUcOtTPk?ZlQ%k8d)qaif+0uVHm+QvS zW};o8_43m-d##|d!kan?7MrGpRtQTQ#o0RW?6B=`o zel!n9dYqP5IMy&70FMPwEGpk`tT-N;&2R>LB<^y1aR1eF) zmde((EKa-CDLS-N%oEYH)tvQ@^lwqBuxqeby)aY{-qD zT}JCaSc!O$S^#dr5IHGT-Z+l`^|a zmR@xg+xIj_NV8bOP!VyA*m(Lpw%^szJGYqq*f@QEAeicKviI>vfW`8W7bB08n-|}L z!uBcKWp{u9jC>%t=NxwlI}ibMx2Atzau0Up*g79)8>1@}u}&KaI@m)yAA+efu1N1yf&)=x{kgKj3nR4a9Sx`xiI zi#A|@o+MY4?myvQM+)N|wVFA$8C{N@+KOsYjCADsGWG*hm{(}G&d*?L=&;9x!_?0K z@&eaQUZ+Z&>SI*e;5R5n2+bOqofq$Yj8+yrIK9|){1*KBb za}2ZjYm)=k{^MDVL8$N&Sl&w$Dn34BakAgiJdxIZYj~ZQ@O+u{yQx!jT7cGbzyR3F zU1Hs!KH*cC%Y!-poa1Y^oJ%z9QhIfzIP+ZX_BZ)&YMO|c2cUO#6?E`@G#!WK4!aWJ z4PMIUM;{!mabU;mQLe|tw!J4`cfedU?AbeN!oZFvZd|KSname0IvmGLxr|>W%oAcg zxJX&{TJJ#b%i#yG9v$X)sF&JFug7)vxo`_RGr4PqvGF)O(E?Rx3-GIO|=l9@Ekl;OJ&JB_< zF!%9O6T7{Yyeo##>;xq7En+VWX&w0J+8qXX^@tGe$?>Tq6Hp%sf@)tMy>HYtX6}Su zx^A#R#LKLio__5oPE~#nMkh1UxWigXYTOLx5K43ypQ%16nnvv5{_Jvjk4HblB5=M# zOcQ~=8kl_Ee(b%umE(o}aEmP${A15oV7XKR)`WbzqUR=jBi183H1c1(Rr zaPUOS#FBTYw~zc%Ai?Z5J>{dBMG93a zsoJdRnP6WperHouUukDFG$`|rj7AC=Ai6Dy#XEh?%TnPRbY$S{b8yPS^tqy8ydKiyLpT4&|)#N09Jly>$4=vnZ;(dC{ zVcpE@-o0lxKNSrpqVT#S*=1sYaG9j0bPVHJxbdbjee_159zPCxo>+32FvW>GLNc$m z@El@X+IPhVY>vi2re*rNZ$%!whgyZsxRkJOy>1EyXzOj38F5$P3H5 zrkix3R}c8^#lv{=Yef`r+gBc~rE+qRV#(KW_;iMy)hN$-IXLWhwfj3wlqN=yuh_u= z0~T6OH&b-rnUbL?7IMd>6`Yl`Ot-AMLSwK5+rtHgbH^{qF7TTK$mPw2t)?VoHjLAU zY616W+JkA|*wK2=ZDGG?kE_m;TZ8jsbZzx-Z=H(XXBsypa)1K%E({cjQeHN1<39Ts zSw?xaDS^(%Ul-Nhj~>TR*D^P|bho}w@uvKZXC~agdNDY*5;~<9RvZP?xv!Wp`Ul~1DX-R2@n{4xmUwv*Dla?e`0W;wHQ}m0~=VduxA1eR>a-1X)NdQQ-|zU6D0Z((RckKc|uvZ0=KS zgD?n2@x3uOD$hf3Mf}Xj-oL#l!!}e;Qz1ubvjV>nD)wigqU9-2WA#Vt^*GF<{oMQR zQ$=L#>@9uo8Bh5T1F`#Gr41>Gih>00@<+IZGnP*agNN^$o?(^|*S5a2=dAaS zX|Gg-kO&GI7_VlhBjM!#u!I(6T;F!MXTV1-VhVb4<^GXw=DolI0AFETO~e_2nBwMX z4^6M8@y;sf=*gsdE6;?T#W`Krj&cZpUVO$Ue=&;;&?v|{B zicCMsccY?V12s9~lEbq%t=9_v(D22!1$7#{@;PhWV5ChCDp+Ety2#HY%p)0mteYxa zHK}y`r!yU{C*z9Qy{aVn4(J?$78j~*u!;x zr@8YgWLoX&41u&S2*JVc91#{a*tRg-SL-`_1v~?PlrI6%DduYSS)IJ-sk4K9Y!a2& z{@U^RxthEa3zYBSKJ%t~6?(nfA%X#xyBi6odXsl1!Dc?eB_&(=>ilW41yrc~C3tzF zI}WSXaF0b7Q*JN1FIR7~5lP+g5ePSC!2v#yA*AHOCq%CYIfYnc zW^PY+{$|nF78n49pJA=dH~acq+W%^OW--@=@<^7;_)o2;IUu(Xor6P zz!F85vgpP9iInVT z$*L-8*lt^@zm5hEwFdP-a}MXYBO2;4izmO!L+-BNen+aulutY>jyzs=|3(MaDT715 zRl`tFnZ+RVsBY1zO;|YW?~F;jC!-xGM+CH2cW1-;A6(l(25pnt_vLwFutKKAam(PO zR*{*6@2LwbG!2o$C2_neiKUS8YK7o=Ewqy(G?n6}4;k$YC>;+3sx-(jI8%43L&n`* zluCNJWFwOtCqPGa6oqHcx|X(HIMH(Em9=jQNiomo;{{}kT>&DGWSbyi-DYKeHTxK~ zox`QDPww)_hfOs{qI^2;?FMRLE&B{3cIFmEZ%pAoIWCHid3kLlZtf*2$7;H{olaNt ziZFq#XHCcn`C$1Zyok1{TXOcrsNOOQaP6E>9Hl0=e?QpRg3}XSUKuJm?pIVI8d8hR zgvpw55Vi3z+QAPyB*xMAZo9}a=q_x?XZe0|vF=+d^Wb^(j%T710m^gpdmns|qXSH1 za%#>Zf&1X*ar0zPmf&jYHtQa@?kE&r`|e`HEesHtvijto{KQ{UgAS+Tsgq`Ihcaj0 zS@WLP`?a(ga6a>Afs{PI$&bkj;JPhN?vXJz_b@bM4qE?OD|(l)*^}n4%SWD9yIVVJ zthU2H&vGCka5o&0nKaDffWlG6qR4A&xbZfl&W(851iul)=P;f}%^ij(W~!qJf<#$= zUwgkru(8h@P7lD=s4dFD@$t2m@36;6b6g)V)Tn()e{j;OKwK{F!i`qM9=e$>p`x1Q zh>-+|OKt;fQ^< z)kG{d4=ul(Zr@&^=iHO-o~qx75^^Wb@l*e*H2bWH*-tJpUVS7CB(Bmae4@AZ%u>&A z(Mi=>8qYQI=v>0>MC35Jt@btjg{5Mj^Cgyv##_9F*x_)+3S};Z-mC1$K~#RM0?C}| zmAB_-zL^3qx6N#;TNhD@mI{GNcy!Kq*RYnv!p1rbwgOgG{x6oyUdTq|xP$Js8{B0BC zc1}wyH*ry8?|P_KJQ`ut6ds`3M#nrAhV`MZkM30cCHYxHJ8FZ>(?rNv$*A*toQ8xwfTz#d_py94twGFL7(cQ7KnRQdv*&1=oF*@fP%`K<-1t{nXx1lvh1b@ zF`Z*`oq6Ep0%mB4I2Qvh!a0m*UW*4?2l>xu5lg33>nw`v>uZpuPiC7+#$#fO_O8j= zp9_=I8*M5gn^G6;PoC8x7B`*iLddsp8OS~#u1tHvpL(mX`H@Y2_T_X>|0uFP!$}}o za4!Pg1J$6Mg{f-UX13F|j`3$J9Ot0EhdMP9E@iZvs z!kTz(ejZu_ZFH@xZ@$QRpe!H{y?s_`^$Z~a8?XJs?Pf>^Gi_GwUQ*rpMuLNGIfE3! zrP@eRuF}XFu83vmJ$?x8kx!11a8Nr9)w5lkNY~d?T?fytyE+Lb%CVcp7n0Iig4c=y ziMwOB+zR|NG5~-H@72wfG>QJ@i&+9MNpJ|^$E5r<^9GG!uRpj-61H@?MgZt9UP|o! z;NZMQE4tp`GcJ_>kT)#Zx+TQRzBWC5jU{zBM@@Q39HHStBe?aCH6R8kr}Dj{NK|23 zCB!XAPg67vneNL*!jy#`{mE1qdK0_jbQ9fu19;65ARL*-R3_nA{}!iNeA4>(C9TJ% zhZ$LntXefR7~7Kkoc^&0l99sM&t5%)^`gSOHUyHZ1ChZ$8gQQEyD6^p!Glz;NWz~9 z0>HK;{SSdgp9zxEchHDf^*n6o@$q3jscek-IHuv!!rh}N;NfNP-jVqt0)qaP;vbQM zbiyH!k;Q14sm*F@a*>GY=`{)Xp}ef9=7D+ zeTt0E3^u-ICTzD8a@&d%j7>!E-IhHFx|1J%M*@5jVo1h@1tZQ?%6p-717&>572njq z5=)mC@*R+Wnpop){ZRRMeNM7u3`+$CU#@6KJT1tiYhVQZOEV-hq~L9S}sX zljC-~_w*^WE>>uFPyT^2{RZ`#zF9C=Um}{WfFx>Ix`{Phl6$IJZO8xK{nLMWiw8qx zXxsbfZKKIY;y9J=r(#CuL1)rGiYv&9|5VTM9qisaPXjKHdsAG%4PAKhM4&mC^%RV7 z6mmF)UcYSF@cljtMhr0(FF*af7;5j6Ya=i34R?onV9Vvlxi@$l^D&#Ev5%3S4NkpOVW?SC)=ci?40f61 zUXVT5>Do8X4Bnu^5Jm-9WeaJDWXQw9FBDL)(o78ayO$dZK;`%KE?2z3BoaI*JIptN zWzH*mcS>e=K<$-`HKRT8mGs(65}>H0Td`F?&Ih4?2n8gE5*2C7iC;Ml7j~YWXk(sn zn(!#g-yBv+4jq|$K_dI{?%pY+_AC3>dYB1oEusYR@HkIHOiwmEH$)4Y&fF$8b1;Lo zWDkubD?RGYFfy;STvhu7!|adJ1&-fy9(&a7E*2VDrQ~UN>ZyOb;4;%blhwp%6r0LR zsmrzAIe9t>$V{m1Hz#wn03XbUEWz#Al_sw1n#IDT(Bq93u{&FHAWG5_4(*zEGu2;- zhs~fOyhIh%MA^=dfo51J5~&HT%FiEKTTNSbVY&nK-Lahox^atTpWj0Zv_Ve~#P7Z( z+z+Tyn5(51GA?DoP)LaNU2`qRK5X-E5nkBO`I}g#U1CZ1qf?7s{chq_+Tbwvgm#Qg zX?of&J_KZ>U+k^7n6HstFI|OS$&6j$=1@l0dzwp;#%5X^xE*ESZD7{(={NKR&3Z9H z*3X$DJ`TBZ=3?Z!JJg$CV_*iOn61|9@q2pARQ>%Y56iVHdIEed&<)?%{>RlhPiHe_ z*)#S}TI)-i-`g?PMRqDU1>kzC7zV1l2ilD@a0L4^k8Cb0DE)2QIv-C0JI<_kR?aZF z>^IV2=JB?_YJ~V8nR8EF_v)|jR2swF?%?K4_~pVz}_t$ zb&W^lo74Jf-`8<1IxtTmCL1j4T|#3}xNF7pIuDcBIyF9>o-*Hx^zdg&yLU`1&YKwi>mz%XaJK_hB`OHw#T-pH7Ru(r zrKKBwPr8E33|dww5mG|5uv9X^eUGr^6`muXS@1 zzh$p|uO$&dy z5Q-T;6-{cy$HrqM9D7tcsy7H!z|Tm(7CtcjVRr$t5yH*zUB0+%T%GS`*#yn)W)62| z>rg3FU4=c3KLj@Y1wd!ty8qwkRR{p%-LX`X|itwR6c63`;Xf#)+N1;L|B>zT}4Z+aOfn> zUIdQb0suR>mZ?!F&x&AZjV$CB2e71YpNiK-Oag8P{Mlv5c|$0F& za=#Vi<%v{lhRv^+c513wmZyHiOXgUd4Ux1RVEw~-b^2vUI3GXrnmb?T?>u?3-G|&! za8q_D3Z!9mdadu#Xpq%uAYBOXUj`sAJiI3C?UfYv(hHiw73DL#d(Q-=jZ09m;MA)X z3P=an6bUcyzx^XOr$8=`C$-*m(2LK9h^Qipl|`YKC{*_blv;WUk{srFsAv%l31KMydCHqJ zRV$aO&5{fe*nRM(W=INEvG@YN2kuAt1WJfm*uU+mZhpSlBnT!N(9J}5F$>41)K<{_Xd`J_YRy+7wgHg1fIWlZ1*_4 zFM+k>h$@@j5km}4s+Q2>S53Rb_fHjZ<&9@i89Y#;S9lKEKs~#~xR(S0R403!c`TRb z9d0`vpx#2gH*tt3b5x;rO%SMEvoh~LqhZBL^JL3`0kI6#`Q)8@Lup<2dM-sl9)vj>i7_ zyUd8}!jc+({U>~I;~!!({1Y4$3{YY^|Ct%T;0OQLW6XFnN=&d*OLVJ#s?1yHxyNl> zBqN}7?zoX_(UgYX5?cy?T00k*O^T+h3}1h4X%8MdJ7*!`e;U*sBIp9A$Ps-)|hY|lij zHEie&1?K>GS$4&fbbvI|W%#_4?^sk!;%TY$$K7+UxO1(M3G{@A??XwDqhbnWn>|u$ zMo6bk_^N!=zXqpi^HTka813MQnIU1X3PoE@p+J&8$wk43o-3HI=1xn=;d73!SSupv z{Tkjz+LML|DAR40xh$SX*O*pKM$xYFKI@Rte$vLJg@r8bk!fenHMj9HWLA?$_EnDv!Rqn!v@*35<)APXG%Z~W z{Oz+xHmwOeSsO7}5gcq~kx#SurjEgYkRF$79qW6{5mdYr)dc3b5*Qc?gOm*%map*x zYe~Q?>f^2|cP$ZJu=@qK*BRPmia9(WknC>%=5Ax_k`e>PXZifub<+pYb%UzBg*Z$@ z;{CZ++wZ0KeKea1o=(&#tZpSqb~tYKYQI4b9)TJKSs$BmDpKC-2nJsX(a#q%K4|dH z3gBC?j<)JbVM_Xo3a=9`CXPM;!E9pVS|F6EauA`5}6C!fhesLVc4CF?KC+3LJ% z8jee)XVDc84;HhT`uHPBu9ruQU|SRqDLyj6ES{(dMA^a~j|2eEy?5e37WJeNS}mej z5D%P>DAW#D0|px_g&~}!R!JR01jDmhoR|}r8s@`|BeivsZK2DT*EMg7+d0m+lwJ2f zQu)!15sPpxuCC5Za4zQ~CHj;;@=geIx>4g98%+w8{p{=#ITS3*H6w{H-D~H6i@r{t z6)l9$9lMA{{dEv#-yF78(*V@0ioXb|c4vcN}!ya$F^Y+$M z=pRw5D-mg&Xoix}^-mh61#U|}K+$4w{vwr&Y;e<~=Rs|yTKCt@G+BjX+y!#G1X&gq z^%>#KGGzcrSQ&aksCy_?FNt5%)lY5jxLtn5<28L!R&5XE??KKDvj2>Lr{E~tCf%}} z$Ly}E*FyRVx5?(9K#GCC>kG<@L>&)r(1?zO{vzc8y;{VCI5t%t}V zh|&KQYMI!*H`4FEWD>7dK<5Q0`{k5bK4_PRaIVwUCvC_mDhh(1oBWDRO+6(nr zVL@$PAr;?d52rvD6Lct4IMH{kBgN)1$5FqQ3mE|PYVj&xngvMd9cLToi@h}oSy%2m zKM9ddyPX{Mn)6d(@9+PpicYGPUeOLvD|(J$6m!n^w|L~85k}fXo9SBE41VR>_`^Oe zaVazcg4-c|@>?LeJ-1c&+A$)$t6Ol=CLXRd3iJ+B>Z_~ zvCS~QPaA#zOI4$q{;OA_Gs`v=){O}><{-Qwg3c8|Nx5?*On^)2mdXbr#8|K5UZNUN zLhK}r1^{ZO$}%be(Y}XTELJ|g8pdf&EpdJ_oLeDVTSPVN7+E_i6S^KTsah+D!2T(w z<(uZQ1h_>o(lHVje{&)4&z2>wmK7S<%rICVzofQImG{JNFnuqHZcG#E%#Z-s!+97V zss@Be6qpmQPbXVJJFN;>%NeKBi{{YwUYP;`3hY52K;MiK5bH_Mc)ilB(Um=l3E}0w zvU%nGjCkOEz;$4N)0XJX6H0o)J1&p-iBPBx2B0vsU=Y?c!Dc=g3uL(#(<4MP6S}x)l?>+{D8ldAde|= zmh9kOznc6V1BdL`wqZLh^QSo3462^g{KR^$YSG5WTPiRz8TRxIYr9YVnv@-fb=c!?c2@u3nR3;Pv#eGK@ZYQ(2&DFVQ68T}7SmR?2ylDX6P z31+YKs}V$3j-9Y@wNix-K2$Zv+>(IL&Zib)6`uM94Ms6*Z&AGDvYOiJR@&iKe2U~@ zLDT?%)7VHkZ_TP|LEPXzf0A)(TtyN&g#bz4U+43ZeB=rRt+lt22c1Z1pghT^JH8Oi z$_}I4>kg#r=*!Dqz?=0Et#-k(&DU={o!29Rc8Df;Jt)xBm76puN}}Y~day-f5~~!^ zJ3Z1RCc#?wnoVQ_IiCcl_1Cu)it?HQQnl&2i8bI6ycmR$c+ZHM4*~>Toj=wk8g3;@QJjZQtT?ICFl%IE8|{N(y0Q zv$^%xyCNpZmfLMC{frmqJ>HO=dnWi zVePdFvbDjg@um6vQ$wWM@<=Ha6Q-uN)oyug|tE?R%HV zcD2K%Pa3gTY+rqT@^4v|lxkG8Nu+a+ZF%y6WK_sLHkbIvHgPd(jf|5NxnL35U#YyzCRjXOy^aRniNYcoCvS-8{0%d=dXyf^!C zpY;MR)q>MKurKS<)4E7{82b;|+u2+4eK*m+Y^{@|lZEoZiS{f$_mp?<=Io*>+8+nu0Xw-!y%@M;xwmm7Ff9Jiwov+@1Cw7wmk}C9n3jVFB6d|Vl#0zM3 z#bTFOV2EpT3N@jWI7xp^yXGPyHNjGWE2>*ipMRQk@m6!;8 zYz9Zo+2scDW;@w7qHCsmadV}p`xBJFXw7b&@nU3YR0xp%*yDVvKc&M;&?@_HDk9Bm z)mb$MnZ)|dcPIqsOwQ^4k(f?0JvJYFKCpw+#_$q-Y#r5bdfvIF9Z6k>$l#dtPW_0? z6Az33A$GBPv3J>#Ql;Yd$h|amHlSW{9DkMmR|6Sq&(2E?MEYh=ws&!W{9@jz@gvod zhyRz59d|XiR~hU}g3sN4*im4dPOa+wSfp|G;PO|4ZHf^H|9Do_JfW@9(V ze~RXFb4lVoX(FM);=ahhRxSlgB;bSmLmsCO^)T^FHY|bG60Y}4uHtd8xV?aTye70X z&z#Hs70oN*_!N!ML27Iu*mRvjcu?tM1WO&W&jKq`}N(zl~T2!Q@V`5({=l56E_ zJ*>PiI@Pj1G_1mdE!}5o}Id^)ODA}^n5-SeRbb?NE zK^0ria`5;oZzI@?hgahSA2DJc9XAR|gHARL{~A)~|6#$7=8y~0|K4p2B{j=;G93*z zIxKShQot9s)V$3XjjEOi2SB{-Zpo}IZv=!u&B)Qafy ze>-{ds2!HsSE)iPKIk`H_?!9g72Pb(h0VB$QH)Pu7*VrX#5UC<7b`*Dec3n9*2lkb zF7YRW6c7nE-~j;luTv)tW~#%Ry?I)`r`%RO?btxxwEjrsh@~C58*;?0F~zgW-HrdG zqUXA7UWc9)B_!M2ifgW3XV|=!<=pD$`e`Qh`+GPffP~f^r^AaPLA#iLhE8$@qd5x! z0O;>%-_dmq2sxJHb9M+Zd_Y#vtI!qBPrc~5u*FzRK^(U$-e(pVlrOh}100-#IKoy; zhG9-1a6qt7mdTw%P_#2~P(4^|-Ch|`!u}7nBtk-@ynqsX{W=?E)=Ff7=hLs2xdY#& zsdO#v6KMVC!D%FTDne|4kqO=>cz!Z8$9+zQYkDEuo5qApVRLMa0>VN{!_U}tcc~~@ zMeT*uH0bjlZh+&j&T08>pB}CuuN^n72h<>~Rfh#oc=;LpzOr)!e@wy9ujVOA%pkX! zW>$E_^6%sdUsa3}FtjOWs+7Pu9eb!3l8;a$Wo#1YLIr>iJBfxWRDFo{BM36!9U@z< zExif%_NPZo^C=3q7Os_viqF!ev(9M;bK}psT*d_7l3ec?cd{nC;lx~E-4Kx#+vosb zOjMQXyZqUgUJA>`np>%Uq*TbhM%5R$_xNCO+w5$e%h!~vjIAxb$)rOw_4sDDZ{8Ih z88Eho;qu(AYbgtQX~V@QOzwViyH;5>s$ZOpb|E>Oh0~dAN4k*3P}BGUtS`xQ@G{h= zLK=B5GXD%h)^^<32=M7!Gyhd|g_HCJ`F~FSR*w1M;d%g<%6M<;Mp?&$bsIWwaMOdW zxY#N^Eciq0^>X;u2dd-c!WFJ0V#|&{;fn`zpI}jlXtnUUW04>G^`G6$%!mM?Kk&9H zd?GwRR4=T->Fr8ukgfA|{+*^72SCcpq1_=`M=pf${~aW+7mQVh^;X?;JGh_74tuf8 z&sZ+B|Fkl~A%8Q+!w=c(b8tf9)J3e-e^DbI#z%pd3eIWqS5rp8i;qeW6{t!R!~u-A zm7e04cTlhiBd4ri!+wgvzBzGV4MU9Blk62X7Cc?`CbFu>N|^Au*z{LzY{1^f^`+jb z%3f_;VGB-*RaDM>V7qwftJ-fX12-59#6`#xj&i?Jh1P4@_v*!8m~L&A;k6p&8uv6Vs)n-!Bv%udB%BHrZnWI!0yvAoJF5Mf zc&639#`zUAAA&aw*&X+k!G(3O<>owz#v1k7RW{*Ifz2-6t$z4Q(oIjDShrwTx7!x> zOHQ(`@H?~&F>&{ucY-gw?U&h4%U0bZnE|Vud&u{70kPcEJ;;eB`b~L!`}J$pQ(Qh@ znaQ2rqm!N8vS`iG*VbM_HmbCDnh#eiqZNF|+vaO|wo_!E@{pyHCq2(hOGcS>@9QTI zXB_6=v8{4(who&asN9W7B#!XACt8($fTbRR zVZBr8yk(k(;kZ_5J+BTg#kqG7-I-2l-4`oPWuDwL{ZAq{E%Zu@J2L+p@jm~n2H*Pe z>eI3=*5YU|`5t!XpG5R$3(K>--=f`_$$5mE{t`RcWAoTlFYKI*=Eyutz`UTnO%hjm)6;eEbsH zP?6`DU%}R=wk-Ee=eqXyN4OXjji~Dx8DpBv2?8TRzz8&4~6vO5{ZH1B-yX3>7E^lQ7dmG3Dyo3aahXV(|YL9L?6M+co>K8hud zBCJTKj3D;0`ml2nBd9GNt}9Wh&2o9U=jYGP*$;+1*yw;@8;&_HX0!J#h0N7JUMi!O zpb@qHQGM1?BsWfBsvK{h>!G}#XA76&hM=#TSltrklL`_(^B-{$36{j_RXx>2Korskf z9963@=q}tqDXmLPrL$bZJiqhZ{r@gP*Lq^O{5ypH(4{^VaD-$_CWXKo|8C8^Ka0kT zWKOg1kccAZJz)(;QAt(mf4)}`##cM0TfvrgagJ zvmn1R+c|OcIY}z#%%0PyEw=f8fMalgA`!1!@!Fi+0_FoO0Q;xCHGWL@M3$0SL6bwV z)+F1jf1CV1{e;AOamGs4YL|XLQOW}N;QXY=Ggif;0y3gNV}C~$&W&IA@e$?bOQ=@m zEMl?*S?#|hv2VYJFGyJKINk5vv=ovTc$OzP+HwiU!jzFtMU#Wolc5ZNAsBCxiSqFG zU9F7sX~M#08tOs18u(i@WCOf2>GqNHioP43f9Bgmx1Bo0rj$#uER~KV>anmIUES8mU!9s%;K(pG6R?2#ZQl$hTf${nuK6eFyT-nl!#T0entOg6VdfE_PH%Zr^O?fqBCZ$0F?tR#+% zwIl62XlUae$`SX;?h@Qxe-yWS1JJ7N^!#-aVmEJgEKrqVxkrt};6S0g{1&QRW_$<-8;y<(B)owY z68ml@KG7QXnQz5ld!=vVgdF=`=QUsqXhIr@ym!d*--;6u7FFDAA`+O2Ba#Y!F}0|L zTGvK*u6;=hJ=!^ZaK=l#mh8EP#C=%!WrG|yS0q_oBhRbA tx;531`)N8;OI%U_q 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%0A&sLWB!WZNm0%GM;*qPyel6 zx_D7$&`ed`(58MS+`=Iaf>e23Re5{zqC;H-%kE2Cu#f1XbMmwJ*% C@BlzkE%6; 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%0DsDnrbNL=LR* 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

    G)>);nS?7 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 literal 24648 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 LtCH&d@$P>BiGkLL