feat: 完成进港查询与进港移库页面5.5寸手机端适配(设计稿11页全部完成)

进港查询(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 <noreply@anthropic.com>
This commit is contained in:
2026-07-31 22:35:56 +08:00
parent b2a2cce585
commit a33776d959
37 changed files with 2884 additions and 476 deletions

View File

@@ -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,待计重/计重中计数依赖);

View File

@@ -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/1Tab 真实过滤 + 角标双 pageQueryTotal抓包证实携带+

View File

@@ -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<Parcelable>) =
缺口 #28:无 fdate 入参、出参无车牌(提货车辆)/目的港/业务类型。
⚠️ 踩坑:`checkAllClick` 全选后底部「已选 N 项」不更新——批量勾选不走 FlowBus 单卡事件,
必须在 checkAllClick 里同步 selectedCountText
- 「进港查询」`IntImpQueryActivity`module_gjj06 出港查询的进港镜像:三格统计
总票数/已入库/已出库为已加载数据客户端计数(`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_gjj07 出港仓库的进港镜像;**首页菜单实际跳转页,
旧版 `GjjWareHouseActivity` 路由已注释弃用**。差异:卡片/筛选用始发站fdep 入参)替代目的站;
搜索框「运单号/航班号」分流含字母→fno、其余→wbNo抓包证实筛选 5 项无入参(缺口 #25
@@ -1165,8 +1183,10 @@ override fun dispatchRestoreInstanceState(container: SparseArray<Parcelable>) =
双变体首例:手机竖排时间线由 Activity `buildVerticalSteps` 动态构建,平板横向步骤条不动;
手机标题按形态切「运单追踪」)。平板侧滑筛选面板代码已判空守卫(手机变体无 filter_panel
includeBinding 字段为 @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 绑计算属性(进港查询/出港查询代理人已踩过) |
---

View File

@@ -152,5 +152,17 @@
android:exported="true"
tools:replace="android:exported" />
<!-- 进港查询(手机版适配验证页) -->
<activity
android:name="com.lukouguoji.gjj.activity.IntImpQueryActivity"
android:exported="true"
tools:replace="android:exported" />
<!-- 进港移库(手机版适配验证页,后端模块未交付,直启验证 UI -->
<activity
android:name="com.lukouguoji.gjj.activity.IntImpMoveActivity"
android:exported="true"
tools:replace="android:exported" />
</application>
</manifest>

View File

@@ -565,6 +565,27 @@
android:exported="false"
android:screenOrientation="unspecified" />
<!-- 国际进港-进港移库5.5寸手机版专属) -->
<activity
android:name="com.lukouguoji.gjj.activity.IntImpMoveActivity"
android:configChanges="orientation|keyboardHidden"
android:exported="false"
android:screenOrientation="unspecified" />
<!-- 国际进港-进港移库-运单详情5.5寸手机版专属) -->
<activity
android:name="com.lukouguoji.gjj.activity.IntImpMoveDetailActivity"
android:configChanges="orientation|keyboardHidden"
android:exported="false"
android:screenOrientation="unspecified" />
<!-- 国际进港-进港移库-拍照上传5.5寸手机版专属) -->
<activity
android:name="com.lukouguoji.gjj.activity.IntImpMovePhotoActivity"
android:configChanges="orientation|keyboardHidden"
android:exported="false"
android:screenOrientation="unspecified" />
<!-- 国际进港-进港查询 -->
<activity
android:name="com.lukouguoji.gjj.activity.IntImpQueryActivity"

View File

@@ -162,6 +162,13 @@ data class GjcMaWb(
/** 5.5寸手机版:空值统一占位 "--"(空串与 null 都兜底,布局绑定用) */
fun orDash(value: String?): String = if (value.isNullOrEmpty()) "--" else value
/**
* 5.5寸手机版:代理人展示值(名称优先,空则回退代码)。
* 不能在 XML 里用 `??` 兜底——转换器会把 JSON null 归一成空串,`??` 只判 null 不判空串。
*/
val agentDisplay: String?
get() = if (agentName.isNullOrEmpty()) agentCode else agentName
/**
* 5.5寸手机版-出港仓库:卡片状态标签(已清仓=绿 / 未清仓=橙clearNormal 为空视作未清仓)。
* 已清仓时卡片「清仓」按钮置灰不可点。

View File

@@ -0,0 +1,78 @@
package com.lukouguoji.module_base.bean
import androidx.databinding.ObservableBoolean
import com.lukouguoji.module_base.interfaces.ICheck
import java.io.Serializable
/**
* 国际进港移库 Bean5.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 寸手持端展示辅助字段(仅用于手机版布局,不参与序列化) ==========
/** 是否已移库moveState0-待移库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
}

View File

@@ -54,4 +54,26 @@ data class IntImpQueryBean(
// ==================== 其他 ====================
var remark: String? = null, // 备注
var activeId: Long? = null // 有效值
)
) {
/**
* 5.5寸手机版-进港查询:卡片状态标签。
* 已出库 = 出库时间dlvTime非空已入库 = 入库时间inDate非空都为空 = 未入库(灰)。
* 接口无独立状态出参,此判定为前端推断(与平板列表「入库时间/出库时间」两列同源)。
*/
val isQueryOutbound: Boolean
get() = !dlvTime.isNullOrEmpty()
val isQueryStored: Boolean
get() = !inDate.isNullOrEmpty()
/** 5.5寸手机版:空值统一占位 "--"(空串与 null 都兜底,布局绑定用) */
fun orDash(value: String?): String = if (value.isNullOrEmpty()) "--" else value
/**
* 5.5寸手机版:代理人展示值(名称优先,空则回退代码)。
* 不能在 XML 里用 `??` 兜底——转换器会把 JSON null 归一成空串,`??` 只判 null 不判空串。
*/
val agentDisplay: String?
get() = if (agentName.isNullOrEmpty()) agentCode else agentName
}

View File

@@ -272,6 +272,9 @@ interface Constant {
const val IntImpTally = "AppIntImpTally" //理货报告
const val IntImpPickUpRecord = "AppIntImpPickUpRecord" //提取记录
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" //理货

View File

@@ -55,6 +55,7 @@ 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
@@ -882,6 +883,38 @@ interface Api {
@POST("IntExpMove/move")
suspend fun submitIntExpMove(@Body data: RequestBody): BaseResultBean<SimpleResultBean>
/**
* 国际进港移库-分页查询
* 接口路径: /IntImpMove/pageQuery
* ⚠️ 后端暂无该模块2026-07-31 api-doc 核对),按 IntExpMove 命名约定预接,已登记问题清单
*/
@POST("IntImpMove/pageQuery")
suspend fun getIntImpMoveList(@Body data: RequestBody): BaseListBean<IntImpMoveBean>
/**
* 国际进港移库-分页合计
* 接口路径: /IntImpMove/pageQueryTotal
* ⚠️ 后端暂无该模块,同上
*/
@POST("IntImpMove/pageQueryTotal")
suspend fun getIntImpMoveTotal(@Body data: RequestBody): BaseResultBean<ManifestTotalDto>
/**
* 国际进港移库-批量移库
* 接口路径: /IntImpMove/move
* ⚠️ 后端暂无该模块,同上
*/
@POST("IntImpMove/move")
suspend fun submitIntImpMove(@Body data: RequestBody): BaseResultBean<SimpleResultBean>
/**
* 国际进港移库-异常照片上传pic/originalPic/picNumber 三字段规范)
* 接口路径: /IntImpMove/uploadPic
* ⚠️ 后端暂无该模块,同上
*/
@POST("IntImpMove/uploadPic")
suspend fun submitIntImpMovePic(@Body data: RequestBody): BaseResultBean<SimpleResultBean>
/**
* 国际出港库位操作-清仓
* 接口路径: /IntExpStorageUse/updateClear

View File

@@ -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" //国际进港 事故签证
///////////////// 航班查询模块

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 手机版绿色操作按钮:完成态绿实底 + 10dp 圆角(进港移库-拍照上传「确认提交」) -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#0E9F6E" />
<corners android:radius="10dp" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="@color/phone_green" />
<corners android:radius="10dp" />
</shape>
</item>
</selector>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 手机版详情卡片表头:橙色底 + 顶部 12dp 圆角(进港移库-异常照片卡片) -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/phone_amber" />
<corners
android:topLeftRadius="12dp"
android:topRightRadius="12dp" />
</shape>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 手机版照片加号槽位:灰色虚线边框 + 8dp 圆角(进港移库-异常照片) -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/transparent" />
<corners android:radius="8dp" />
<stroke
android:width="1dp"
android:color="@color/phone_divider"
android:dashGap="4dp"
android:dashWidth="4dp" />
</shape>

View File

@@ -79,5 +79,6 @@
<color name="phone_tag_indigo_text">#6366F1</color>
<color name="phone_tag_amber_bg">#FEF3C7</color> <!-- 状态标签-琥珀底(出港运抵申报状态 E -->
<color name="phone_tag_amber_text">#D97706</color>
<color name="phone_amber">#F59E0B</color> <!-- 橙色信息卡表头(进港移库-异常照片) -->
</resources>

View File

@@ -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="代理人:中外运" />

View File

@@ -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<ActivityIntImpMoveBinding, IntImpMoveViewModel>() {
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<String>(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) {
viewModel.onItemCheckChanged()
}
// 监听刷新事件
FlowBus.with<String>(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))
}
}
}

View File

@@ -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<ActivityIntImpMoveDetailBinding, IntImpMoveDetailViewModel>() {
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))
)
}
}
}

View File

@@ -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<ActivityIntImpMovePhotoBinding, IntImpMovePhotoViewModel>() {
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))
)
}
}
}

View File

@@ -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

View File

@@ -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
/**
* 国际进港移库列表项 ViewHolder5.5 寸手持端专属页面)
*
* 卡片交互:
* · 勾选框点击 → 切换选中并通知 Activity 更新全选/已选计数
* · 「查看详情」→ 运单详情页
* · 卡片长按 → 「拍照」操作浮层XML 绑定 activity 回调)
*/
class IntImpMoveViewHolder(view: View) :
BaseViewHolder<IntImpMoveBean, ItemIntImpMoveBinding>(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<String>(ConstantEvent.EVENT_CHECK_CHANGED).emit("check_changed")
}
}
binding.executePendingBindings()
}
}

View File

@@ -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表示修改操作
}
}

View File

@@ -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
/**
* 国际进港移库「运单详情」ViewModel5.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)
}
}
}

View File

@@ -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
/**
* 国际进港移库「拍照上传」ViewModel5.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<FileBean>()
.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 -> {}
}
}
}

View File

@@ -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
/**
* 国际进港移库 ViewModel5.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<List<KeyValue>>(emptyList())
val awbTypeList = MutableLiveData<List<KeyValue>>(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<IntImpMoveBean>()
CheckUtil.handleAllCheck(list)
updateCheckAllStatus()
adapter.notifyDataSetChanged()
}
/**
* 更新全选状态与已选计数
*/
fun updateCheckAllStatus() {
val adapter = pageModel.rv?.commonAdapter() ?: return
val list = adapter.items.filterIsInstance<IntImpMoveBean>()
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<IntImpMoveBean> {
val adapter = pageModel.rv?.commonAdapter() ?: return emptyList()
return adapter.items.filterIsInstance<IntImpMoveBean>().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<String, Any>()
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<String, Any>) {
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 中处理
}
}

View File

@@ -64,6 +64,24 @@ class IntImpQueryViewModel : BasePageViewModel(), IOnItemClickListener {
val awbTypeList = MutableLiveData<List<KeyValue>>(emptyList())
val businessTypeList = MutableLiveData<List<KeyValue>>(emptyList())
// ==================== 5.5寸手机版专属 ====================
// 三格统计:已入库 / 已出库(总票数复用 totalCount为服务端全量口径
// pageQueryTotal 无分项统计出参——已入库/已出库为「已加载数据」客户端计数口径,
// 与卡片状态标签同一判定dlvTime / inDate见 IntImpQueryBean
val storedCount = MutableLiveData("0")
val outboundCount = MutableLiveData("0")
private var phoneExtrasEnabled = false
private var phoneLoadedList: List<IntImpQueryBean> = 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) {

View File

@@ -0,0 +1,234 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<import type="com.lukouguoji.module_base.ui.weight.search.layout.SearchLayoutType" />
<variable
name="viewModel"
type="com.lukouguoji.gjj.viewModel.IntImpQueryViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f2"
android:orientation="vertical">
<!-- 标题栏(始终在最上层,不被遮挡) -->
<include layout="@layout/title_tool_bar" />
<!-- 内容区域FrameLayout 包裹,筛选面板和遮罩只在此区域内) -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<!-- 原有内容 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- 搜索区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- 航班日期起 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
hint='@{"请选择开始日期"}'
icon="@{@drawable/img_date}"
type="@{SearchLayoutType.DATE}"
value="@={viewModel.flightDateStart}" />
<!-- 航班日期止 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
hint='@{"请选择结束航班日期"}'
icon="@{@drawable/img_date}"
type="@{SearchLayoutType.DATE}"
value="@={viewModel.flightDateEnd}" />
<!-- 代理人 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
hint='@{"请选择代理"}'
list="@{viewModel.agentList}"
type="@{SearchLayoutType.SPINNER}"
value="@={viewModel.agentId}" />
<!-- 出库状态 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
hint='@{"请选择出库状态"}'
list="@{viewModel.outStatusList}"
type="@{SearchLayoutType.SPINNER}"
value="@={viewModel.outStatus}" />
<!-- 运单号 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
hint='@{"请输入运单号"}'
icon="@{@drawable/img_scan}"
setOnIconClickListener="@{()-> viewModel.waybillScanClick()}"
type="@{SearchLayoutType.INPUT}"
value="@={viewModel.waybillNo}"
autoQueryEnabled="@{true}"
autoQueryUrl="@{`/IntImpSearch/queryWbNoList`}"
autoQueryParamKey="@{`wbNo`}"
autoQueryMinLength="@{4}"
autoQueryMaxLength="@{8}"
autoQueryTitle="@{`选择运单号`}" />
<!-- 搜索和筛选按钮 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical|start"
android:orientation="horizontal"
android:paddingHorizontal="24dp">
<ImageView
android:layout_width="36dp"
android:layout_height="36dp"
android:onClick="@{()-> viewModel.searchClick()}"
android:padding="2dp"
android:src="@drawable/img_search" />
<FrameLayout
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginLeft="16dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:onClick="@{()-> viewModel.filterClick()}"
android:padding="5dp"
android:src="@drawable/img_filter" />
<View
android:layout_width="8dp"
android:layout_height="8dp"
android:layout_gravity="top|end"
android:background="@drawable/bg_red_dot"
android:visibility="@{viewModel.hasFilter ? View.VISIBLE : View.GONE}" />
</FrameLayout>
</LinearLayout>
</LinearLayout>
<!-- 列表区域 -->
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/srl"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_int_imp_query" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<!-- 底部统计信息 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/white"
android:gravity="center_vertical"
android:paddingHorizontal="15dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{`合计:` + viewModel.totalCount + `票`}'
android:textColor="@color/bottom_tool_tips_text_color"
android:textSize="16sp"
android:textStyle="bold"
tools:text="合计3票" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text='@{`总件数:` + viewModel.totalPc}'
android:textColor="@color/bottom_tool_tips_text_color"
android:textSize="16sp"
android:textStyle="bold"
tools:text="总件数100" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text='@{`总重量:` + viewModel.totalWeight}'
android:textColor="@color/bottom_tool_tips_text_color"
android:textSize="16sp"
android:textStyle="bold"
tools:text="总重量100" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<!-- 遮罩层(只覆盖内容区域) -->
<View
android:id="@+id/filter_overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#80000000"
android:clickable="true"
android:focusable="true"
android:onClick="@{()-> viewModel.closeFilter()}"
android:visibility="gone" />
<!-- 筛选面板(从右侧滑入,只在内容区域内) -->
<include
android:id="@+id/filter_panel"
layout="@layout/layout_int_imp_query_filter"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:visibility="gone"
app:viewModel="@{viewModel}" />
</FrameLayout>
</LinearLayout>
</layout>

View File

@@ -0,0 +1,325 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="bean"
type="com.lukouguoji.module_base.bean.IntImpQueryBean" />
</data>
<!-- 外层容器承载间距 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="5dp"
android:orientation="vertical">
<!-- 侧滑布局 -->
<com.mcxtzhang.swipemenulib.SwipeMenuLayout
android:id="@+id/swipe_menu"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- 主列表项容器 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_item"
android:orientation="horizontal"
android:paddingVertical="20dp"
android:paddingHorizontal="10dp">
<!-- 左侧图标 -->
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:src="@drawable/img_plane" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:orientation="vertical">
<!-- 第一行:运单号、件数、重量、代理人、航班信息 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- 运单号 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{4}"
android:text="运单号:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text="@{bean.wbNo}"
android:textColor="@color/colorPrimary"
tools:text="78109081212" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 件数 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.6"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{3}"
android:text="件数:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text='@{String.valueOf(bean.inPc)}'
tools:text="10" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 重量 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{5}"
android:text="重量:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text='@{String.valueOf(bean.inWeight)}'
tools:text="200" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 代理人 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{5}"
android:text="代理人:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text='@{bean.agentName}'
tools:text="SF" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 航班信息 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{5}"
android:text="航班信息:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text='@{bean.flight}'
tools:text="20240216/MU2026" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 第二行:航程、特码、运单类型、入库时间、出库时间 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
<!-- 航程 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{4}"
android:text="航程:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text="@{bean.range}"
tools:text="LAX-HFE" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 特码 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.6"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{3}"
android:text="特码:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text="@{bean.spCode}"
tools:text="NOR" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 运单类型 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{5}"
android:text="运单类型:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text='@{bean.awbName}'
tools:text="国际进港" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 入库时间 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{5}"
android:text="入库时间:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text='@{bean.inDate}'
tools:text="2024-05-13 17:10:22" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 出库时间 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{5}"
android:text="出库时间:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text='@{bean.dlvTime}'
tools:text="2024-05-13 17:10:22" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</LinearLayout>
<!-- 右侧箭头 -->
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:src="@drawable/img_pda_right" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 侧滑菜单按钮区 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<!-- 修改按钮 -->
<TextView
android:id="@+id/btn_edit"
style="@style/tv_item_action"
android:background="@color/colorPrimary"
android:text="修改" />
</androidx.appcompat.widget.LinearLayoutCompat>
</com.mcxtzhang.swipemenulib.SwipeMenuLayout>
</LinearLayout>
</layout>

View File

@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
国际进港移库 —— 5.5 寸手持端专属页面无平板变体Pad 端首页也无此菜单)
结构镜像 layout/activity_int_exp_move.xml国际出港移库手机版
· 顶部搜索框(运单号,含扫码)+ 筛选弹层(航班日期 / 航班号 / 特码 / 运单类型)
· 「待移库 / 已移库」Tab 绑定 viewModel.moveState"0" / "1"
· 已移库 Tab 下隐藏底部操作条(与设计稿一致)
· 卡片长按出「拍照」浮层(见 item_int_imp_move.xml
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<import type="com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayoutType" />
<variable
name="viewModel"
type="com.lukouguoji.gjj.viewModel.IntImpMoveViewModel" />
<variable
name="activity"
type="com.lukouguoji.gjj.activity.IntImpMoveActivity" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/phone_page_bg">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<!-- ==================== 搜索行 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingTop="16dp"
android:paddingBottom="12dp">
<com.lukouguoji.module_base.ui.weight.phone.PhoneSearchBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"搜索运单号"}'
setOnFilterClickListener="@{(v)-> activity.toggleFilterPanel()}"
setOnScanClickListener="@{(v)-> activity.scanWaybill()}"
setRefreshCallBack="@{viewModel::searchClick}"
upperCase="@{true}"
value="@={viewModel.waybillNo}" />
</LinearLayout>
<!-- ==================== 待移库 / 已移库 Tab ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneStatusTab
android:layout_width="match_parent"
android:layout_height="wrap_content"
counts="@{viewModel.moveStateCounts}"
setOnTabChanged="@{viewModel::searchClick}"
tabs="@{viewModel.moveStateTabs}"
value="@={viewModel.moveState}" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/phone_divider" />
<!-- ==================== 列表 ==================== -->
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/srl"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:overScrollMode="never"
android:paddingBottom="12dp"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="3"
tools:listitem="@layout/item_int_imp_move" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<!-- ==================== 底部操作条(已移库 Tab 下隐藏) ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneBottomBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
actionText='@{"移库"}'
allChecked="@{viewModel.isAllChecked}"
countText='@{"已选 " + viewModel.selectedCount + " 项"}'
setOnActionClick="@{(v)-> activity.showMoveConfirmDialog()}"
setOnAllCheckClick="@{(v)-> viewModel.toggleSelectAll()}"
android:visibility="@{`1`.equals(viewModel.moveState) ? View.GONE : View.VISIBLE}" />
</LinearLayout>
<!-- ==================== 筛选弹层 ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFilterPanel
android:layout_width="match_parent"
android:layout_height="match_parent"
panelVisible="@{activity.filterPanelVisible}"
setOnConfirmClick="@{(v)-> activity.confirmFilter()}"
setOnDismissClick="@{(v)-> activity.toggleFilterPanel()}"
setOnResetClick="@{(v)-> activity.resetFilter()}"
title='@{"筛选条件"}'>
<!-- 航班日期 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择航班日期"}'
title='@{"航班日期"}'
type="@{PhoneDataLayoutType.DATE}"
value="@={viewModel.flightDate}" />
<!-- 航班号 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:id="@+id/phone_filter_flight_no"
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请输入航班号"}'
title='@{"航班号"}'
type="@{PhoneDataLayoutType.INPUT}"
value="@={viewModel.flightNo}" />
<!-- 特码 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择特码"}'
list="@{viewModel.spCodeList}"
title='@{"特码"}'
type="@{PhoneDataLayoutType.SPINNER}"
value="@={viewModel.spCode}" />
<!-- 运单类型 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择运单类型"}'
list="@{viewModel.awbTypeList}"
title='@{"运单类型"}'
type="@{PhoneDataLayoutType.SPINNER}"
value="@={viewModel.awbType}" />
</com.lukouguoji.module_base.ui.weight.phone.PhoneFilterPanel>
</FrameLayout>
</layout>

View File

@@ -0,0 +1,334 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
国际进港移库「运单详情」—— 5.5 寸手持端专属页面(无平板变体)
对应设计稿 11_进港移库 的「运单详情」页:
· 卡片一:蓝色表头(运单号 + 绿点 + 移库时间)+ 类型标签行(红「国际进港」= 运单类型)
+ 品名大字 + 两列字段网格(件数/重量/特码/代理/出运路径/承运人)
· 卡片二:绿色表头「移库信息」+ 移库人 / 移库时间(仅已移库显示)
· 卡片三:橙色表头「异常照片」+ 三个虚线加号槽位(点击跳拍照上传页)
字段全部由列表项带入,不额外请求接口(后端暂无 IntImpMove 模块,问题清单已登记)。
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<variable
name="viewModel"
type="com.lukouguoji.gjj.viewModel.IntImpMoveDetailViewModel" />
<variable
name="activity"
type="com.lukouguoji.gjj.activity.IntImpMoveDetailActivity" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/phone_page_bg"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- ==================== 卡片一:运单基本信息 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card"
android:orientation="vertical">
<!-- 蓝色表头:运单号 + 绿点 + 移库时间 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card_header_blue"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp"
android:paddingVertical="12dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@{viewModel.dataBean.wbNo}"
android:textColor="@color/white"
android:textSize="17sp"
android:textStyle="bold" />
<View
android:layout_width="8dp"
android:layout_height="8dp"
android:layout_marginEnd="6dp"
android:background="@drawable/bg_phone_dot_green" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.opdate)}"
android:textColor="@color/white"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- 类型标签行:运单类型(红标签) + 业务类型 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="22dp"
android:background="@drawable/bg_phone_tag_red"
android:gravity="center"
android:paddingHorizontal="8dp"
android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.awbTypeName)}"
android:textColor="@color/phone_tag_red_text"
android:textSize="12sp"
android:textStyle="bold" />
<View
android:layout_width="1dp"
android:layout_height="14dp"
android:layout_marginHorizontal="10dp"
android:background="@color/phone_divider" />
<TextView
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:textColor="@color/phone_text_body"
android:textSize="14sp" />
</LinearLayout>
<!-- 品名(主字段大字) -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.goodsName)}"
android:textColor="@color/phone_text_strong"
android:textSize="22sp"
android:textStyle="bold" />
<!-- 第 1 行:件数 / 重量 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
title='@{"件数"}'
value="@{String.valueOf(viewModel.dataBean.pc)}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_weight="1"
title='@{"重量"}'
value='@{String.valueOf((int)viewModel.dataBean.weight) + " kg"}' />
</LinearLayout>
<!-- 第 2 行:特码 / 代理 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
title='@{"特码"}'
value="@{viewModel.dataBean.spCode}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_weight="1"
title='@{"代理"}'
value="@{viewModel.dataBean.agentName.empty ? viewModel.dataBean.agentCode : viewModel.dataBean.agentName}" />
</LinearLayout>
<!-- 第 3 行:出运路径 / 承运人 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
title='@{"出运路径"}'
value="@{viewModel.dataBean.range}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_weight="1"
title='@{"承运人"}'
value="@{viewModel.dataBean.by1}" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<!-- ==================== 卡片二:移库信息(仅已移库显示) ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/bg_phone_card"
android:orientation="vertical"
android:visibility="@{viewModel.dataBean.isMoved ? View.VISIBLE : View.GONE}">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card_header_green"
android:paddingHorizontal="16dp"
android:paddingVertical="10dp"
android:text="移库信息"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="16dp"
android:paddingVertical="12dp">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
title='@{"移库人"}'
value="@{viewModel.dataBean.opId}" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_weight="1"
title='@{"移库时间"}'
value="@{viewModel.dataBean.opdate}" />
</LinearLayout>
</LinearLayout>
<!-- ==================== 卡片三:异常照片 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/bg_phone_card"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card_header_orange"
android:paddingHorizontal="16dp"
android:paddingVertical="10dp"
android:text="异常照片"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold" />
<!-- 三个虚线加号槽位(等宽正方形由 weight + 固定高实现),点击进拍照上传页 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<TextView
android:layout_width="0dp"
android:layout_height="96dp"
android:layout_weight="1"
android:background="@drawable/bg_phone_photo_add"
android:gravity="center"
android:onClick="@{()-> activity.openPhoto()}"
android:text="+"
android:textColor="@color/phone_text_hint"
android:textSize="24sp" />
<TextView
android:layout_width="0dp"
android:layout_height="96dp"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:background="@drawable/bg_phone_photo_add"
android:gravity="center"
android:onClick="@{()-> activity.openPhoto()}"
android:text="+"
android:textColor="@color/phone_text_hint"
android:textSize="24sp" />
<TextView
android:layout_width="0dp"
android:layout_height="96dp"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:background="@drawable/bg_phone_photo_add"
android:gravity="center"
android:onClick="@{()-> activity.openPhoto()}"
android:text="+"
android:textColor="@color/phone_text_hint"
android:textSize="24sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
</layout>

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
国际进港移库「拍照上传」—— 5.5 寸手持端专属页面(无平板变体)
对应设计稿 11_进港移库/photo.html
· 白卡「运单照片上传」+ 图片预览网格(复用公共 ImageSelectNewViewHolder末位加号槽位
· 底部两个按钮:拍照/上传(蓝) + 确认提交(绿)
提交走 pic/originalPic/picNumber 三字段规范(后端暂无 IntImpMove 模块,问题清单已登记)。
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.lukouguoji.gjj.viewModel.IntImpMovePhotoViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/phone_page_bg"
android:orientation="vertical">
<include layout="@layout/title_tool_bar" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card"
android:orientation="vertical"
android:padding="16dp">
<!-- 标题:运单照片上传(副行展示运单号) -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="运单照片上传"
android:textColor="@color/phone_text_strong"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@{viewModel.dataBean.wbNo}"
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="78133363573" />
<!-- 图片预览网格(末位加号槽位,长按出删除角标) -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:overScrollMode="never"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="3"
tools:itemCount="3" />
<!-- 底部按钮:拍照/上传(蓝) + 确认提交(绿) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="44dp"
android:layout_weight="1"
android:background="@drawable/bg_phone_btn_primary"
android:gravity="center"
android:onClick="@{()-> viewModel.pickClick()}"
android:text="拍照/上传"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="44dp"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:background="@drawable/bg_phone_btn_green"
android:gravity="center"
android:onClick="@{()-> viewModel.submitClick()}"
android:text="确认提交"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
</layout>

View File

@@ -1,205 +1,201 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
国际进港查询 —— 手机版布局5.5 寸手持端,最小宽度 < 600dp 时生效)
平板版为同名文件 layout-sw600dp/activity_int_imp_query.xml两者是同一布局的资源变体
DataBinding 因此生成同一个 ActivityIntImpQueryBinding 类。
变体之间必须满足:
· DataBinding 变量完全一致viewModel
· 保留 Activity 中引用的控件 idsrl / rv
· 平板独有的 filter_overlay / filter_panel侧滑筛选手机版不提供
Binding 基类中自动变 @NullableIntImpQueryActivity 已判空处理
交互差异(均复用既有 IntImpQueryViewModel 字段与接口):
· 平板 5 个横排搜索条 → 手机顶部搜索框(运单号)+ 底部筛选弹层
(航班日期起/止、代理从搜索行移入弹层;设计稿无「出库状态」项,未提供)
· 三格统计(总票数/已入库/已出库后两格为手机专属客户端计数initPhoneExtras 开启)
· 筛选弹层显隐直接绑既有 viewModel.filterVisible无需平板的滑入动画代码
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<import type="com.lukouguoji.module_base.ui.weight.search.layout.SearchLayoutType" />
<import type="com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayoutType" />
<variable
name="viewModel"
type="com.lukouguoji.gjj.viewModel.IntImpQueryViewModel" />
</data>
<LinearLayout
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f2"
android:orientation="vertical">
android:background="@color/phone_page_bg">
<!-- 标题栏(始终在最上层,不被遮挡) -->
<include layout="@layout/title_tool_bar" />
<!-- 内容区域FrameLayout 包裹,筛选面板和遮罩只在此区域内) -->
<FrameLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
android:layout_height="match_parent"
android:orientation="vertical">
<!-- 原有内容 -->
<include layout="@layout/title_tool_bar" />
<!-- ==================== 搜索行 ==================== -->
<LinearLayout
android:layout_width="match_parent"
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">
<!-- 搜索区域 -->
<LinearLayout
<com.lukouguoji.module_base.ui.weight.phone.PhoneSearchBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
hint='@{"搜索运单号"}'
setOnFilterClickListener="@{(v)-> viewModel.filterClick()}"
setOnScanClickListener="@{(v)-> viewModel.waybillScanClick()}"
setRefreshCallBack="@{viewModel::searchClick}"
value="@={viewModel.waybillNo}" />
</LinearLayout>
<!-- ==================== 三格统计:总票数 / 已入库 / 已出库 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<!-- 总票数(蓝) -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/bg_phone_card"
android:orientation="horizontal">
<!-- 航班日期起 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
hint='@{"请选择开始日期"}'
icon="@{@drawable/img_date}"
type="@{SearchLayoutType.DATE}"
value="@={viewModel.flightDateStart}" />
<View
android:layout_width="4dp"
android:layout_height="match_parent"
android:layout_marginVertical="12dp"
android:background="@color/phone_primary" />
<!-- 航班日期止 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
hint='@{"请选择结束航班日期"}'
icon="@{@drawable/img_date}"
type="@{SearchLayoutType.DATE}"
value="@={viewModel.flightDateEnd}" />
<!-- 代理人 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
hint='@{"请选择代理"}'
list="@{viewModel.agentList}"
type="@{SearchLayoutType.SPINNER}"
value="@={viewModel.agentId}" />
<!-- 出库状态 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
hint='@{"请选择出库状态"}'
list="@{viewModel.outStatusList}"
type="@{SearchLayoutType.SPINNER}"
value="@={viewModel.outStatus}" />
<!-- 运单号 -->
<com.lukouguoji.module_base.ui.weight.search.layout.PadSearchLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
hint='@{"请输入运单号"}'
icon="@{@drawable/img_scan}"
setOnIconClickListener="@{()-> viewModel.waybillScanClick()}"
type="@{SearchLayoutType.INPUT}"
value="@={viewModel.waybillNo}"
autoQueryEnabled="@{true}"
autoQueryUrl="@{`/IntImpSearch/queryWbNoList`}"
autoQueryParamKey="@{`wbNo`}"
autoQueryMinLength="@{4}"
autoQueryMaxLength="@{8}"
autoQueryTitle="@{`选择运单号`}" />
<!-- 搜索和筛选按钮 -->
<LinearLayout
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical|start"
android:orientation="horizontal"
android:paddingHorizontal="24dp">
android:orientation="vertical"
android:paddingHorizontal="12dp"
android:paddingVertical="10dp">
<ImageView
android:layout_width="36dp"
android:layout_height="36dp"
android:onClick="@{()-> viewModel.searchClick()}"
android:padding="2dp"
android:src="@drawable/img_search" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="总票数"
android:textColor="@color/phone_text_body"
android:textSize="12sp" />
<FrameLayout
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginLeft="16dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:onClick="@{()-> viewModel.filterClick()}"
android:padding="5dp"
android:src="@drawable/img_filter" />
<View
android:layout_width="8dp"
android:layout_height="8dp"
android:layout_gravity="top|end"
android:background="@drawable/bg_red_dot"
android:visibility="@{viewModel.hasFilter ? View.VISIBLE : View.GONE}" />
</FrameLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@{viewModel.totalCount}"
android:textColor="@color/phone_primary"
android:textSize="20sp"
android:textStyle="bold"
tools:text="4" />
</LinearLayout>
</LinearLayout>
<!-- 列表区域 -->
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/srl"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_int_imp_query" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<!-- 底部统计信息 -->
<!-- 已入库(橙) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/white"
android:gravity="center_vertical"
android:paddingHorizontal="15dp">
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">
<View
android:layout_width="4dp"
android:layout_height="match_parent"
android:layout_marginVertical="12dp"
android:background="@color/phone_tag_orange_text" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
android:orientation="vertical"
android:paddingHorizontal="12dp"
android:paddingVertical="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{`合计:` + viewModel.totalCount + `票`}'
android:textColor="@color/bottom_tool_tips_text_color"
android:textSize="16sp"
android:textStyle="bold"
tools:text="合计3票" />
android:text="已入库"
android:textColor="@color/phone_text_body"
android:textSize="12sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text='@{`总件数:` + viewModel.totalPc}'
android:textColor="@color/bottom_tool_tips_text_color"
android:textSize="16sp"
android:layout_marginTop="2dp"
android:text="@{viewModel.storedCount}"
android:textColor="@color/phone_tag_orange_text"
android:textSize="20sp"
android:textStyle="bold"
tools:text="总件数100" />
tools:text="2" />
</LinearLayout>
</LinearLayout>
<!-- 已出库(绿) -->
<LinearLayout
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">
<View
android:layout_width="4dp"
android:layout_height="match_parent"
android:layout_marginVertical="12dp"
android:background="@color/phone_tag_green_text" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="12dp"
android:paddingVertical="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text='@{`总重量:` + viewModel.totalWeight}'
android:textColor="@color/bottom_tool_tips_text_color"
android:textSize="16sp"
android:text="已出库"
android:textColor="@color/phone_text_body"
android:textSize="12sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@{viewModel.outboundCount}"
android:textColor="@color/phone_tag_green_text"
android:textSize="20sp"
android:textStyle="bold"
tools:text="总重量100" />
tools:text="2" />
</LinearLayout>
@@ -207,28 +203,131 @@
</LinearLayout>
<!-- 遮罩层(只覆盖内容区域) -->
<View
android:id="@+id/filter_overlay"
<!-- ==================== 列表 ==================== -->
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/srl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#80000000"
android:clickable="true"
android:focusable="true"
android:onClick="@{()-> viewModel.closeFilter()}"
android:visibility="gone" />
android:layout_height="0dp"
android:layout_weight="1">
<!-- 筛选面板(从右侧滑入,只在内容区域内) -->
<include
android:id="@+id/filter_panel"
layout="@layout/layout_int_imp_query_filter"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:visibility="gone"
app:viewModel="@{viewModel}" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:overScrollMode="never"
android:paddingTop="4dp"
android:paddingBottom="24dp"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="3"
tools:listitem="@layout/item_int_imp_query" />
</FrameLayout>
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
</LinearLayout>
<!-- ==================== 筛选弹层(绑既有 filterVisible ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneFilterPanel
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="8dp"
panelVisible="@{viewModel.filterVisible}"
setOnConfirmClick="@{(v)-> viewModel.confirmFilter()}"
setOnDismissClick="@{(v)-> viewModel.closeFilter()}"
setOnResetClick="@{(v)-> viewModel.resetFilter()}"
title='@{"筛选条件"}'>
<!-- 航班日期起(平板搜索行字段,手机移入弹层) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择航班日期"}'
title='@{"航班日期起"}'
type="@{PhoneDataLayoutType.DATE}"
value="@={viewModel.flightDateStart}" />
<!-- 航班日期止 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择航班日期"}'
title='@{"航班日期止"}'
type="@{PhoneDataLayoutType.DATE}"
value="@={viewModel.flightDateEnd}" />
<!-- 航班号 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:id="@+id/phone_filter_flight_no"
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请输入航班号"}'
title='@{"航班号"}'
type="@{PhoneDataLayoutType.INPUT}"
value="@={viewModel.flightNo}" />
<!-- 代理(平板搜索行字段,手机移入弹层) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择代理"}'
list="@{viewModel.agentList}"
title='@{"代理"}'
type="@{PhoneDataLayoutType.SPINNER}"
value="@={viewModel.agentId}" />
<!-- 特码(复用平板筛选面板同一字典 spCodeList -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择特码"}'
list="@{viewModel.spCodeList}"
title='@{"特码"}'
type="@{PhoneDataLayoutType.SPINNER}"
value="@={viewModel.spCode}" />
<!-- 始发站 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:id="@+id/phone_filter_origin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请输入始发站"}'
title='@{"始发站"}'
type="@{PhoneDataLayoutType.INPUT}"
value="@={viewModel.origin}" />
<!-- 运单类型 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择运单类型"}'
list="@{viewModel.awbTypeList}"
title='@{"运单类型"}'
type="@{PhoneDataLayoutType.SPINNER}"
value="@={viewModel.awbType}" />
<!-- 业务类型 -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请选择业务类型"}'
list="@{viewModel.businessTypeList}"
title='@{"业务类型"}'
type="@{PhoneDataLayoutType.SPINNER}"
value="@={viewModel.businessType}" />
<!-- 品名(中) -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
hint='@{"请输入品名"}'
title='@{"品名(中)"}'
type="@{PhoneDataLayoutType.INPUT}"
value="@={viewModel.goodsCn}" />
</com.lukouguoji.module_base.ui.weight.phone.PhoneFilterPanel>
</FrameLayout>
</LinearLayout>
</layout>

View File

@@ -0,0 +1,230 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
国际进港移库 —— 列表项5.5 寸手持端专属页面,无平板变体)
结构镜像 layout/item_int_exp_move.xml国际出港移库手机版差异
· 航班信息为真实字段bean.flightInfo进港接口出参约定 fdate/fno
· 长按卡片出「拍照」浮层(紫色圆钮,跳拍照上传页),点浮层空白处收起
一套布局覆盖设计稿两种卡片形态,按 bean.isMoved 切换:
· 待移库:圆形勾选框 + 蓝色运单号 + 橙色「待移库」标签
· 已移库:无勾选框 + 深色运单号 + 绿色对勾「已移库」
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="bean"
type="com.lukouguoji.module_base.bean.IntImpMoveBean" />
<variable
name="position"
type="Integer" />
<variable
name="activity"
type="com.lukouguoji.gjj.activity.IntImpMoveActivity" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="12dp"
android:layout_marginTop="12dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card"
android:onLongClick="@{()-> activity.showCardActionPhone(bean)}"
android:orientation="vertical"
android:padding="16dp">
<!-- ==================== 卡片头部:勾选框 + 运单号 + 状态 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- 圆形勾选框(已移库的记录不可勾选,隐藏) -->
<ImageView
android:id="@+id/iv_icon"
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}" />
<!-- 运单号 -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@{bean.wbNo}"
android:textColor="@{bean.isMoved ? @color/phone_text_title : @color/phone_primary}"
android:textSize="15sp"
android:textStyle="bold" />
<!-- 待移库:橙色状态标签 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginStart="8dp"
android:background="@drawable/bg_phone_tag_orange"
android:gravity="center"
android:paddingHorizontal="8dp"
android:text="待移库"
android:textColor="@color/phone_tag_orange_text"
android:textSize="11sp"
android:visibility="@{bean.isMoved ? View.GONE : View.VISIBLE}" />
<!-- 已移库:对勾 + 状态文字 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="@{bean.isMoved ? View.VISIBLE : View.GONE}">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_phone_check_circle" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:text="已移库"
android:textColor="@color/phone_text_title"
android:textSize="13sp" />
</LinearLayout>
</LinearLayout>
<!-- ==================== 航班信息行 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_airplane" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_weight="1"
android:text='@{"航班信息:" + bean.orDash(bean.flightInfo)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="航班信息20260709/MU2311" />
</LinearLayout>
<!-- ==================== 统计框:特码 / 件数 / 重量 ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneStatBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
label1='@{"特码"}'
label2='@{"件数"}'
label3='@{"重量"}'
value1="@{bean.orDash(bean.spCode)}"
value2='@{bean.pc + "件"}'
value3='@{String.valueOf((int)bean.weight) + "kg"}' />
<!-- ==================== 出运路径 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_location" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_weight="1"
android:text='@{"出运路径:" + bean.orDash(bean.range)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp" />
</LinearLayout>
<!-- ==================== 查看详情 ==================== -->
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginTop="16dp"
android:background="@color/phone_stat_bg" />
<LinearLayout
android:id="@+id/ll_detail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|end"
android:orientation="horizontal"
android:paddingTop="12dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="查看详情"
android:textColor="@color/phone_primary"
android:textSize="14sp" />
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_phone_chevron_right" />
</LinearLayout>
</LinearLayout>
<!-- ==================== 长按操作浮层:拍照 ==================== -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#66000000"
android:clickable="true"
android:onClick="@{()-> activity.hideCardActionPhone(bean)}"
android:visibility="@{bean.actionMenuVisible ? View.VISIBLE : View.GONE}">
<TextView
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_gravity="center"
android:background="@drawable/bg_phone_fab_purple"
android:gravity="center"
android:onClick="@{()-> activity.openPhoto(bean)}"
android:text="拍照"
android:textColor="@color/white"
android:textSize="12sp"
android:textStyle="bold" />
</FrameLayout>
</FrameLayout>
</layout>

View File

@@ -1,325 +1,226 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
国际进港查询 —— 列表项手机版布局5.5 寸手持端,最小宽度 < 600dp 时生效)
平板版为同名文件 layout-sw600dp/item_int_imp_query.xml两者是同一布局的资源变体
DataBinding 因此生成同一个 ItemIntImpQueryBinding 类。
变体之间必须满足:
· DataBinding 变量完全一致bean
· 保留 IntImpQueryViewHolder 引用的控件 idll整卡点击进详情
· 平板侧滑「修改」按钮swipe_menu/btn_edit手机版不提供设计稿无编辑入口
编辑走详情页头部入口ViewHolder 里已判空,安全
状态标签按 bean 计算属性切换(前端推断,见 IntImpQueryBean 注释):
· 已出库(绿)= dlvTime 非空
· 已入库(橙)= inDate 非空
· 未入库(灰)= 兜底
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="bean"
type="com.lukouguoji.module_base.bean.IntImpQueryBean" />
</data>
<!-- 外层容器承载间距 -->
<LinearLayout
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="5dp"
android:orientation="vertical">
<!-- 侧滑布局 -->
<com.mcxtzhang.swipemenulib.SwipeMenuLayout
android:id="@+id/swipe_menu"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- 主列表项容器 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_item"
android:orientation="horizontal"
android:paddingVertical="20dp"
android:paddingHorizontal="10dp">
<!-- 左侧图标 -->
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:src="@drawable/img_plane" />
android:layout_marginHorizontal="16dp"
android:layout_marginTop="12dp"
android:background="@drawable/bg_phone_card"
android:orientation="vertical"
android:padding="14dp">
<!-- ==================== 头行:蓝点 + 运单号 + 状态标签 + 箭头 ==================== -->
<LinearLayout
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:orientation="vertical">
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- 第一行:运单号、件数、重量、代理人、航班信息 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_width="8dp"
android:layout_height="8dp"
android:layout_marginEnd="8dp"
android:background="@drawable/bg_phone_dot_blue" />
<!-- 运单号 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{4}"
android:text="运单号:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text="@{bean.wbNo}"
android:textColor="@color/colorPrimary"
tools:text="78109081212" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 件数 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.6"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{3}"
android:text="件数:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text='@{String.valueOf(bean.inPc)}'
tools:text="10" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 重量 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{5}"
android:text="重量:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text='@{String.valueOf(bean.inWeight)}'
tools:text="200" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 代理人 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{5}"
android:text="代理人:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text='@{bean.agentName}'
tools:text="SF" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 航班信息 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{5}"
android:text="航班信息:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text='@{bean.flight}'
tools:text="20240216/MU2026" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 第二行:航程、特码、运单类型、入库时间、出库时间 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
android:layout_weight="1"
android:text="@{bean.wbNo}"
android:textColor="@color/phone_text_title"
android:textSize="16sp"
android:textStyle="bold"
tools:text="78133363396" />
<!-- 航程 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical">
<!-- 已出库(绿) -->
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
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.isQueryOutbound ? View.VISIBLE : View.GONE}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{4}"
android:text="航程:" />
<!-- 已入库(橙) -->
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginStart="8dp"
android:background="@drawable/bg_phone_tag_orange"
android:gravity="center"
android:paddingHorizontal="8dp"
android:text="已入库"
android:textColor="@color/phone_tag_orange_text"
android:textSize="11sp"
android:visibility="@{!bean.isQueryOutbound &amp;&amp; bean.isQueryStored ? View.VISIBLE : View.GONE}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text="@{bean.range}"
tools:text="LAX-HFE" />
<!-- 未入库(灰,兜底) -->
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginStart="8dp"
android:background="@drawable/bg_phone_tag_gray"
android:gravity="center"
android:paddingHorizontal="8dp"
android:text="未入库"
android:textColor="@color/phone_tag_gray_text"
android:textSize="11sp"
android:visibility="@{!bean.isQueryOutbound &amp;&amp; !bean.isQueryStored ? View.VISIBLE : View.GONE}" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 特码 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.6"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{3}"
android:text="特码:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text="@{bean.spCode}"
tools:text="NOR" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 运单类型 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{5}"
android:text="运单类型:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text='@{bean.awbName}'
tools:text="国际进港" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 入库时间 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{5}"
android:text="入库时间:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text='@{bean.inDate}'
tools:text="2024-05-13 17:10:22" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 出库时间 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
completeSpace="@{5}"
android:text="出库时间:" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text='@{bean.dlvTime}'
tools:text="2024-05-13 17:10:22" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="6dp"
android:src="@drawable/ic_phone_chevron_right" />
</LinearLayout>
<!-- 右侧箭头 -->
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:src="@drawable/img_pda_right" />
<!-- ==================== 字段网格:件数/重量 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- 侧滑菜单按钮区 -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="match_parent"
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- 修改按钮 -->
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_package" />
<TextView
android:id="@+id/btn_edit"
style="@style/tv_item_action"
android:background="@color/colorPrimary"
android:text="修改" />
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" />
</androidx.appcompat.widget.LinearLayoutCompat>
</LinearLayout>
</com.mcxtzhang.swipemenulib.SwipeMenuLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
</LinearLayout>
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_weight" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:text='@{"重量:" + (bean.inWeight != null ? String.valueOf(bean.inWeight) : "--")}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="重量555" />
</LinearLayout>
</LinearLayout>
<!-- ==================== 字段网格:代理人/特码 ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_person" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:text='@{"代理人:" + bean.orDash(bean.agentDisplay)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="代理人:中外运" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:src="@drawable/ic_phone_tag" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:text='@{"特码:" + bean.orDash(bean.spCode)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="特码DGR" />
</LinearLayout>
</LinearLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
</layout>

View File

@@ -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,

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB