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 4f3435e..59eab0a 100644 Binary files a/documents/后端接口对接问题清单.xlsx and b/documents/后端接口对接问题清单.xlsx differ 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 fb47c05..38c926d 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 @@ -148,6 +148,20 @@ data class GjcMaWb( else -> 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 0000000..76433e2 Binary files /dev/null and b/module_p/src/main/res/drawable-xxhdpi/gjc_query_icon.png differ