diff --git a/.claude/skills/phone-adapt/references/api-doc.md b/.claude/skills/phone-adapt/references/api-doc.md index b7358d6..8634cee 100644 --- a/.claude/skills/phone-adapt/references/api-doc.md +++ b/.claude/skills/phone-adapt/references/api-doc.md @@ -70,6 +70,14 @@ curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \ 0 正常/1 故障(三态需求=缺口 #7);无「来源」字段(#8)、无 `checkInDate`/`ifNo` 筛选入参(#9)、 无批量删除(#10,`deleteUld` 是 `@Query` 单条);出参 `ifNo`/`efNo`/`checkInDate`/`checkOutDate` 文档无描述,按命名推断进/出港航班号与出入库时间(#11 待确认) +- `IntExpCheckIn`(出港计重,2026-07-29 内网实测):`likeNo` **并非任意模糊**——按 8 位 `no` + 匹配(11 位 wbNo 或部分号均 0 条),11 位全号必须走 `wbNo`;`checkIn`/`checkInList` + 文档有定义但 `pageQuery`/`pageQueryTotal` **均静默忽略**(缺口 #12,待计重/计重中计数依赖); + 查询入参无通道号/承运人/运单类型(#13)、`checked/*` 无收运时间范围(#14);`checked/pageQuery` + 出参无通道号(#15)但有 `userName`(计重人中文名);`listRecordByWh` 出参计重人仅 `opId`(#16); + `preArrive` 成功后 `pageQuery` 的 `arriveFlag` 不回填(#17);`splitCheckIn`/`completeCheckIn` + 无 `palletNumber`/`carWeight` 入参(#18,手机版托盘数量/自重按设计稿传预留参数); + 运单类型字典:`DictUtils.getWaybillTypeList2(ieFlag="E", type="IO")` ## 内网直调验证技巧(比驱动 UI 快得多) diff --git a/.claude/skills/phone-adapt/references/components.md b/.claude/skills/phone-adapt/references/components.md index 5d9bc39..bc747d4 100644 --- a/.claude/skills/phone-adapt/references/components.md +++ b/.claude/skills/phone-adapt/references/components.md @@ -122,11 +122,13 @@ android.util.Log.d("DBG", "value '$field' -> '$v'", Throwable("trace")) `phone_divider` `phone_badge_bg` `phone_green` `phone_check_border` `phone_tag_gray_*` `phone_tag_green_*` `phone_tag_red_*` `phone_orange_bg/text` - 背景:`bg_phone_card` `bg_phone_search` `bg_phone_input` `bg_phone_stat_box` `bg_phone_panel_top` - `bg_phone_icon_round` `bg_phone_btn_primary` `bg_phone_btn_outline` `bg_phone_badge` - `bg_phone_tag_green/gray/red/orange` `bg_phone_card_header_blue/green` + `bg_phone_icon_round` `bg_phone_btn_primary` `bg_phone_btn_outline` `bg_phone_btn_weak`(浅蓝弱按钮) + `bg_phone_badge` `bg_phone_tag_green/gray/red/orange` `bg_phone_card_header_blue/green` + `bg_phone_card_top_accent`(卡片顶部主色描边条,出港计重头部卡片) - 图标:`ic_phone_airplane` `ic_phone_location` `ic_phone_person` `ic_phone_check_circle` `ic_phone_chevron_right/down` `ic_phone_calendar` `ic_phone_close` `ic_phone_check_round_checked/unchecked`(圆形复选框) + `ic_phone_clipboard`(剪贴板,白色 FAB 用)`ic_phone_weight`(砝码,可 tint) - 复用 Pad 的矢量图:`img_search` `img_scan` `img_filter`(可 `app:tint` 染色) 设计稿里的 MDI 图标若缺失,直接写 24×24 的 vector(用 MDI 官方 path),比找位图靠谱且能染色。 diff --git a/CHANGELOG.md b/CHANGELOG.md index d23c007..c2753ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,28 @@ ## [Unreleased] ### 新增 (Added) +- 「出港计重」5.5 寸手机端适配(首个全链路 4+1 页模块,设计稿 03_出港计重): + 待计重列表(三格统计 总票数/待计重/计重中 + 卡片状态标签 未计重/计重中 + 卡片内单票「提前运抵」+ + FAB 进计重记录 + 筛选弹层 通道号/承运人/运单类型/代理人)、开始计重(头部预配统计卡 + PhoneFormRow 表单, + 托盘数量/托盘自重按设计稿手输)、计重记录(三格统计 + 卡片地磅图标进明细/「查看详情」进运单详情 + + 筛选弹层 入库日期起止/代理人/特码/目的站/计重人)、计重明细(汇总卡含托盘总重 + 记录卡「修改」→ + 全屏「修改记录」覆层,复用平板 isEditMode 编辑链路,保存后留在本页)、手机专属新页「运单详情」 + `GjcWeighingWbDetailActivity`(12 字段只读网格);手机首页「国际」Tab 增「出港计重」入口 +- 新增手机版公共资源:`bg_phone_btn_weak`(浅蓝弱按钮)、`bg_phone_card_top_accent`(卡片顶部主色描边条)、 + `ic_phone_clipboard`、`ic_phone_weight` +- `GjcMaWb` 预留 `palletNumber`/`carWeight` 字段、`GjcCheckInRecord` 增 `carWeightStr` 双向绑定属性 + (均为手机版专属,平板请求体零变化);后端缺口 7 项登记问题清单 #12~#18 + (checkIn 过滤不生效、主列表筛选三入参、入库日期范围、通道号出参、计重人姓名、arriveFlag 不回填、 + 托盘数量/自重入参) + +### 修复 (Fixed) +- 出港计重手机版搜索分流按实测修正:`likeNo` 并非任意模糊(按 8 位 no 匹配), + 11 位全号改走 `wbNo` 精确查询,含字母走 `fno` + +### 验证 (Verified) +- 出港计重双端实机验证通过:手机端 待计重列表/筛选/开始计重(必填校验)/计重记录/记录筛选/运单详情/ + 计重明细/修改覆层保存/单票提前运抵 全链路 crash=0、方向无闪屏、请求体新参数全部正确携带; + 平板端 待计重/计重记录/开始计重 三页回归无变化(横屏、5 搜索条、日期默认今天、地磅区/托盘车号/浮动按钮组均在) - 「ULD管理」5.5 寸手机端适配(app 模块首个适配页):列表卡片(三色状态标签)+ 筛选弹层(入库时间/进港航班号/所属航司/来源)+ 右下角浮动新增 + 底部全选/批量删除(循环调用单条删除接口)+ 一套 `activity_uld_edit` 手机布局覆盖 新增/修改/详情 三态 (详情态右上铅笔进入修改、状态底部选择面板、所在港默认 HFE、必填校验仅手机生效) diff --git a/CLAUDE.md b/CLAUDE.md index fa2bfc2..9be348d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1054,6 +1054,8 @@ DataBinding 适配器统一放在 `PhoneWidgetKtx.kt`(同名属性按控件类 `PhoneBottomBar` 追加 `actionDanger` 属性:true 时主按钮转浅红底红字 + 垃圾桶图标(ULD 管理批量删除)。 新增资源:`bg_phone_btn_danger`、`bg_phone_fab`(圆形浮动 + 按钮)、`bg_phone_tag_red_light`(浅红标签)、 `ic_phone_trash`、`ic_phone_edit`、色值 `phone_danger_bg/text`。 +出港计重追加:`bg_phone_btn_weak`(浅蓝弱按钮,卡片内提前运抵)、`bg_phone_card_top_accent` +(卡片顶部主色描边条)、`ic_phone_clipboard`(FAB 剪贴板)、`ic_phone_weight`(砝码图标,可 tint)。 ⚠️ **弹层与浮动按钮的层级**:`PhoneFilterPanel` 默认无 elevation,页面里有带 elevation 的浮动按钮(FAB)时 会穿透到弹层之上——给弹层实例加 `android:elevation="8dp"`(大于 FAB 的 6dp)。 @@ -1102,6 +1104,12 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = (公共组件首个完整落地页,双端实机验证通过) - 「ULD管理」`UldListActivity` + `UldEditActivity`(app 模块首个适配页;一套编辑布局覆盖 新增/修改/详情三态;批量删除为前端循环调用单条接口;状态三态/来源等 5 项后端缺口见问题清单 #7~#11) + - 「出港计重」全链路 4+1 页:`GjcWeighingListActivity`(待计重列表,三格统计 + 卡片单票提前运抵 + + FAB 进记录)、`GjcWeighingStartActivity`(开始计重,托盘数量/自重按设计稿手输)、 + `GjcWeighingRecordListActivity`(计重记录)、`GjcWeighingRecordDetailsActivity`(计重明细, + isEditMode 复用为手机全屏「修改记录」覆层)+ 手机专属新页 `GjcWeighingWbDetailActivity`(运单详情)。 + 搜索分流规则(实测):含字母→fno、11 位数字→wbNo、其余→likeNo(likeNo 按 8 位 no 匹配并非模糊); + checkIn 过滤等 7 项后端缺口见问题清单 #12~#18 - ⏳ **待办**: - `PhoneSearchBar` 接入 AutoQuery 联想(`AutoQueryManager` 目前只对接了 Pad 系组件) - 出库交接 Tab 角标恒 0:`IntExpOutHandover/pageQueryTotal` 出参恒 0(后端缺陷,问题清单 #6), diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml index 0ecb42d..3fabae5 100644 --- a/app/src/debug/AndroidManifest.xml +++ b/app/src/debug/AndroidManifest.xml @@ -50,5 +50,35 @@ android:exported="true" tools:replace="android:exported" /> + + + + + + + + + + + + + + + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e0d5ebd..cc1e1d7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -205,6 +205,12 @@ android:configChanges="orientation|keyboardHidden" android:exported="false" android:screenOrientation="unspecified" /> + + + + + + + diff --git a/module_base/src/main/res/drawable/bg_phone_card_top_accent.xml b/module_base/src/main/res/drawable/bg_phone_card_top_accent.xml new file mode 100644 index 0000000..b551906 --- /dev/null +++ b/module_base/src/main/res/drawable/bg_phone_card_top_accent.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_clipboard.xml b/module_base/src/main/res/drawable/ic_phone_clipboard.xml new file mode 100644 index 0000000..980d0ed --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_clipboard.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/module_base/src/main/res/drawable/ic_phone_weight.xml b/module_base/src/main/res/drawable/ic_phone_weight.xml new file mode 100644 index 0000000..ebec08a --- /dev/null +++ b/module_base/src/main/res/drawable/ic_phone_weight.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt index a0e37bb..f657b23 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingListActivity.kt @@ -3,19 +3,26 @@ package com.lukouguoji.gjc.activity import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.databinding.ObservableBoolean import com.alibaba.android.arouter.facade.annotation.Route import com.lukouguoji.gjc.R import com.lukouguoji.gjc.databinding.ActivityGjcWeighingListBinding import com.lukouguoji.gjc.viewModel.GjcWeighingViewModel import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.GjcWeighingBean import com.lukouguoji.module_base.common.ConstantEvent import com.lukouguoji.module_base.impl.FlowBus import com.lukouguoji.module_base.impl.observe import com.lukouguoji.module_base.ktx.getLifecycleOwner import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil /** * 国际出港计重列表页 + * + * 布局 id 不区分设备,平板/手机由资源限定符自动选择: + * layout-sw600dp/activity_gjc_weighing_list.xml(平板) + * layout/activity_gjc_weighing_list.xml(手机) */ @Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_LIST) class GjcWeighingListActivity : @@ -25,10 +32,20 @@ class GjcWeighingListActivity : override fun viewModelClass() = GjcWeighingViewModel::class.java + /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ + val filterPanelVisible = ObservableBoolean(false) + override fun initOnCreate(savedInstanceState: Bundle?) { setBackArrow("国际出港待计重") binding.viewModel = viewModel + binding.activity = this + + // 手机版专属数据:放开默认日期、加载筛选弹层字典、启用三格统计 + // 平板端不调用,查询链路与请求次数与改造前完全一致 + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } // 初始化代理人列表(从API获取) viewModel.initAgentList() @@ -52,6 +69,32 @@ class GjcWeighingListActivity : viewModel.refresh() } + // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 字段) ==================== + + /** 手机版筛选弹层显隐切换 */ + fun toggleFilterPanel() { + filterPanelVisible.set(!filterPanelVisible.get()) + } + + /** 手机版筛选:重置(只清弹层内条件,不影响顶部搜索框) */ + fun resetFilter() { + viewModel.channelFilter.value = "" + viewModel.carrierFilter.value = "" + viewModel.awbTypeFilter.value = "" + viewModel.agentCode.value = "" + } + + /** 手机版筛选:确认 */ + fun confirmFilter() { + filterPanelVisible.set(false) + viewModel.searchClick() + } + + /** 手机版卡片内「提前运抵」(单票,由 ViewHolder 调用) */ + fun preArriveClick(bean: GjcWeighingBean) { + viewModel.arrivedAheadSingle(bean) + } + companion object { @JvmStatic fun start(context: Context) { diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordDetailsActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordDetailsActivity.kt index b9ace48..f2c6887 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordDetailsActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordDetailsActivity.kt @@ -12,12 +12,17 @@ import com.lukouguoji.gjc.holder.GjcCheckInRecordViewHolder import com.lukouguoji.gjc.viewModel.GjcWeighingRecordDetailsViewModel import com.lukouguoji.module_base.base.BaseBindingActivity import com.lukouguoji.module_base.base.CommonAdapter +import com.lukouguoji.module_base.bean.GjcCheckInRecord import com.lukouguoji.module_base.bean.GjcWeighingRecordBean import com.lukouguoji.module_base.common.Constant import com.lukouguoji.module_base.router.ARouterConstants /** * 国际出港计重明细页 + * + * 布局 id 不区分设备,平板/手机由资源限定符自动选择: + * layout-sw600dp/activity_gjc_weighing_record_details.xml(平板,列表内联编辑) + * layout/activity_gjc_weighing_record_details.xml(手机,单条记录经全屏「修改记录」覆层编辑) */ @Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_DETAILS) class GjcWeighingRecordDetailsActivity : @@ -70,6 +75,23 @@ class GjcWeighingRecordDetailsActivity : viewModel.initOnCreated(intent) } + // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 编辑链路) ==================== + + /** + * 手机版:打开「修改记录」覆层编辑指定记录。 + * 复用 [GjcWeighingRecordDetailsViewModel.onModifyClick] 的备份/编辑态逻辑, + * 覆层显隐由 isEditMode 驱动(平板端该状态驱动列表内联编辑,互不影响)。 + */ + fun openPhoneEdit(record: GjcCheckInRecord) { + viewModel.onModifyClick() + binding.editRecord = record + } + + /** 手机版:取消编辑(恢复备份并收起覆层) */ + fun closePhoneEdit() { + viewModel.onCancelClick() + } + companion object { @JvmStatic fun start(context: Context, bean: GjcWeighingRecordBean) { diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt index 5d6253e..bb83248 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingRecordListActivity.kt @@ -3,6 +3,7 @@ package com.lukouguoji.gjc.activity import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.databinding.ObservableBoolean import com.alibaba.android.arouter.facade.annotation.Route import com.lukouguoji.gjc.R import com.lukouguoji.gjc.databinding.ActivityGjcWeighingRecordListBinding @@ -13,9 +14,14 @@ import com.lukouguoji.module_base.impl.FlowBus import com.lukouguoji.module_base.impl.observe import com.lukouguoji.module_base.ktx.getLifecycleOwner import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil /** * 国际出港计重记录列表页 + * + * 布局 id 不区分设备,平板/手机由资源限定符自动选择: + * layout-sw600dp/activity_gjc_weighing_record_list.xml(平板) + * layout/activity_gjc_weighing_record_list.xml(手机) */ @Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_LIST) class GjcWeighingRecordListActivity : @@ -25,10 +31,20 @@ class GjcWeighingRecordListActivity : override fun viewModelClass() = GjcWeighingRecordViewModel::class.java + /** 手机版筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ + val filterPanelVisible = ObservableBoolean(false) + override fun initOnCreate(savedInstanceState: Bundle?) { setBackArrow("国际出港计重记录") binding.viewModel = viewModel + binding.activity = this + + // 手机版专属数据:放开默认日期、加载计重人下拉 + // 平板端不调用,查询链路与请求次数与改造前完全一致 + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } // 初始化代理人列表 viewModel.initAgentList() @@ -50,6 +66,29 @@ class GjcWeighingRecordListActivity : viewModel.refresh() } + // ==================== 手机版专用交互(纯 UI,复用既有 ViewModel 字段) ==================== + + /** 手机版筛选弹层显隐切换 */ + fun toggleFilterPanel() { + filterPanelVisible.set(!filterPanelVisible.get()) + } + + /** 手机版筛选:重置(只清弹层内条件,不影响顶部搜索框) */ + fun resetFilter() { + viewModel.checkInDateStart.value = "" + viewModel.checkInDateEnd.value = "" + viewModel.agentCode.value = "" + viewModel.spCode.value = "" + viewModel.destFilter.value = "" + viewModel.opUserFilter.value = "" + } + + /** 手机版筛选:确认 */ + fun confirmFilter() { + filterPanelVisible.set(false) + viewModel.searchClick() + } + companion object { @JvmStatic fun start(context: Context) { diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingStartActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingStartActivity.kt index 168ed21..937534d 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingStartActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingStartActivity.kt @@ -15,6 +15,7 @@ import com.lukouguoji.gjc.viewModel.GjcWeighingStartViewModel import com.lukouguoji.module_base.base.BaseBindingActivity import com.lukouguoji.module_base.common.Constant import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil /** * 国际出港计重-开始计重页面 @@ -32,26 +33,38 @@ class GjcWeighingStartActivity : override fun initOnCreate(savedInstanceState: Bundle?) { setBackArrow("国际出港开始计重") binding.viewModel = viewModel + + // 手机版专属:提交体携带托盘数量/托盘自重(平板不调用,请求体与改造前完全一致) + if (DeviceUtil.isPhone()) { + viewModel.initPhoneExtras() + } + viewModel.initOnCreated(this, intent) setupFloatButtons() } private fun setupFloatButtons() { + // 浮动按钮组仅平板布局存在(layout-sw600dp),手机布局无这些 id,直接跳过 + val mainFloatButton = binding.mainFloatButton ?: return + val maskView = binding.maskView ?: return + val subButton1 = binding.subButton1 ?: return + val subButton2 = binding.subButton2 ?: return + // 主按钮点击事件 - binding.mainFloatButton.setOnClickListener { + mainFloatButton.setOnClickListener { if (!isExpanded) { expandButtons() } } // 遮罩层点击事件 - binding.maskView.setOnClickListener { + maskView.setOnClickListener { collapseButtons() } // 子按钮1点击事件 - 跳转到出港运抵页面 - binding.subButton1.setOnClickListener { + subButton1.setOnClickListener { com.alibaba.android.arouter.launcher.ARouter.getInstance() .build(ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE) .navigation() @@ -59,7 +72,7 @@ class GjcWeighingStartActivity : } // 子按钮2点击事件 - 跳转到计重记录 - binding.subButton2.setOnClickListener { + subButton2.setOnClickListener { com.alibaba.android.arouter.launcher.ARouter.getInstance() .build(ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_LIST) .navigation() @@ -68,37 +81,42 @@ class GjcWeighingStartActivity : } /** - * 展开子按钮 + * 展开子按钮(仅平板,手机布局无浮动按钮组) */ private fun expandButtons() { + val mainFloatButton = binding.mainFloatButton ?: return + val maskView = binding.maskView ?: return + val subButton1 = binding.subButton1 ?: return + val subButton2 = binding.subButton2 ?: return + isExpanded = true // 显示遮罩层 - binding.maskView.visibility = View.VISIBLE - binding.maskView.alpha = 0f - binding.maskView.animate().alpha(0.3f).setDuration(200).start() + maskView.visibility = View.VISIBLE + maskView.alpha = 0f + maskView.animate().alpha(0.3f).setDuration(200).start() // 显示子按钮 - binding.subButton1.visibility = View.VISIBLE - binding.subButton2.visibility = View.VISIBLE + subButton1.visibility = View.VISIBLE + subButton2.visibility = View.VISIBLE // 子按钮1动画(向左上方移动: 左移15dp, 上移55dp) - val sub1TransX = ObjectAnimator.ofFloat(binding.subButton1, "translationX", 0f, -5f) - val sub1TransY = ObjectAnimator.ofFloat(binding.subButton1, "translationY", 0f, -25f) - val sub1Alpha = ObjectAnimator.ofFloat(binding.subButton1, "alpha", 0f, 1f) - val sub1Scale = ObjectAnimator.ofFloat(binding.subButton1, "scaleX", 0f, 1f) - val sub1ScaleY = ObjectAnimator.ofFloat(binding.subButton1, "scaleY", 0f, 1f) + val sub1TransX = ObjectAnimator.ofFloat(subButton1, "translationX", 0f, -5f) + val sub1TransY = ObjectAnimator.ofFloat(subButton1, "translationY", 0f, -25f) + val sub1Alpha = ObjectAnimator.ofFloat(subButton1, "alpha", 0f, 1f) + val sub1Scale = ObjectAnimator.ofFloat(subButton1, "scaleX", 0f, 1f) + val sub1ScaleY = ObjectAnimator.ofFloat(subButton1, "scaleY", 0f, 1f) val animSet1 = AnimatorSet() animSet1.playTogether(sub1TransX, sub1TransY, sub1Alpha, sub1Scale, sub1ScaleY) animSet1.duration = 200 // 子按钮2动画(向左下方移动: 左移55dp, 下移15dp) - val sub2TransX = ObjectAnimator.ofFloat(binding.subButton2, "translationX", 0f, -25f) - val sub2TransY = ObjectAnimator.ofFloat(binding.subButton2, "translationY", 0f, -5f) - val sub2Alpha = ObjectAnimator.ofFloat(binding.subButton2, "alpha", 0f, 1f) - val sub2Scale = ObjectAnimator.ofFloat(binding.subButton2, "scaleX", 0f, 1f) - val sub2ScaleY = ObjectAnimator.ofFloat(binding.subButton2, "scaleY", 0f, 1f) + val sub2TransX = ObjectAnimator.ofFloat(subButton2, "translationX", 0f, -25f) + val sub2TransY = ObjectAnimator.ofFloat(subButton2, "translationY", 0f, -5f) + val sub2Alpha = ObjectAnimator.ofFloat(subButton2, "alpha", 0f, 1f) + val sub2Scale = ObjectAnimator.ofFloat(subButton2, "scaleX", 0f, 1f) + val sub2ScaleY = ObjectAnimator.ofFloat(subButton2, "scaleY", 0f, 1f) val animSet2 = AnimatorSet() animSet2.playTogether(sub2TransX, sub2TransY, sub2Alpha, sub2Scale, sub2ScaleY) @@ -106,14 +124,14 @@ class GjcWeighingStartActivity : animSet2.startDelay = 50 // 主按钮隐藏动画 - binding.mainFloatButton.animate() + mainFloatButton.animate() .scaleX(0f) .scaleY(0f) .alpha(0f) .setDuration(150) .setListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { - binding.mainFloatButton.visibility = View.GONE + mainFloatButton.visibility = View.GONE } }) .start() @@ -123,33 +141,38 @@ class GjcWeighingStartActivity : } /** - * 收起子按钮 + * 收起子按钮(仅平板,手机布局无浮动按钮组) */ private fun collapseButtons() { + val mainFloatButton = binding.mainFloatButton ?: return + val maskView = binding.maskView ?: return + val subButton1 = binding.subButton1 ?: return + val subButton2 = binding.subButton2 ?: return + isExpanded = false // 隐藏遮罩层 - binding.maskView.animate().alpha(0f).setDuration(200).withEndAction { - binding.maskView.visibility = View.GONE + maskView.animate().alpha(0f).setDuration(200).withEndAction { + maskView.visibility = View.GONE }.start() // 子按钮1动画(回到原位) - val sub1TransX = ObjectAnimator.ofFloat(binding.subButton1, "translationX", binding.subButton1.translationX, 0f) - val sub1TransY = ObjectAnimator.ofFloat(binding.subButton1, "translationY", binding.subButton1.translationY, 0f) - val sub1Alpha = ObjectAnimator.ofFloat(binding.subButton1, "alpha", 1f, 0f) - val sub1Scale = ObjectAnimator.ofFloat(binding.subButton1, "scaleX", 1f, 0f) - val sub1ScaleY = ObjectAnimator.ofFloat(binding.subButton1, "scaleY", 1f, 0f) + val sub1TransX = ObjectAnimator.ofFloat(subButton1, "translationX", subButton1.translationX, 0f) + val sub1TransY = ObjectAnimator.ofFloat(subButton1, "translationY", subButton1.translationY, 0f) + val sub1Alpha = ObjectAnimator.ofFloat(subButton1, "alpha", 1f, 0f) + val sub1Scale = ObjectAnimator.ofFloat(subButton1, "scaleX", 1f, 0f) + val sub1ScaleY = ObjectAnimator.ofFloat(subButton1, "scaleY", 1f, 0f) val animSet1 = AnimatorSet() animSet1.playTogether(sub1TransX, sub1TransY, sub1Alpha, sub1Scale, sub1ScaleY) animSet1.duration = 200 // 子按钮2动画(回到原位) - val sub2TransX = ObjectAnimator.ofFloat(binding.subButton2, "translationX", binding.subButton2.translationX, 0f) - val sub2TransY = ObjectAnimator.ofFloat(binding.subButton2, "translationY", binding.subButton2.translationY, 0f) - val sub2Alpha = ObjectAnimator.ofFloat(binding.subButton2, "alpha", 1f, 0f) - val sub2Scale = ObjectAnimator.ofFloat(binding.subButton2, "scaleX", 1f, 0f) - val sub2ScaleY = ObjectAnimator.ofFloat(binding.subButton2, "scaleY", 1f, 0f) + val sub2TransX = ObjectAnimator.ofFloat(subButton2, "translationX", subButton2.translationX, 0f) + val sub2TransY = ObjectAnimator.ofFloat(subButton2, "translationY", subButton2.translationY, 0f) + val sub2Alpha = ObjectAnimator.ofFloat(subButton2, "alpha", 1f, 0f) + val sub2Scale = ObjectAnimator.ofFloat(subButton2, "scaleX", 1f, 0f) + val sub2ScaleY = ObjectAnimator.ofFloat(subButton2, "scaleY", 1f, 0f) val animSet2 = AnimatorSet() animSet2.playTogether(sub2TransX, sub2TransY, sub2Alpha, sub2Scale, sub2ScaleY) @@ -157,19 +180,19 @@ class GjcWeighingStartActivity : animSet1.addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { - binding.subButton1.visibility = View.GONE + subButton1.visibility = View.GONE } }) animSet2.addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { - binding.subButton2.visibility = View.GONE + subButton2.visibility = View.GONE } }) // 主按钮显示动画 - binding.mainFloatButton.visibility = View.VISIBLE - binding.mainFloatButton.animate() + mainFloatButton.visibility = View.VISIBLE + mainFloatButton.animate() .scaleX(1f) .scaleY(1f) .alpha(1f) diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingWbDetailActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingWbDetailActivity.kt new file mode 100644 index 0000000..906a9b2 --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcWeighingWbDetailActivity.kt @@ -0,0 +1,40 @@ +package com.lukouguoji.gjc.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityGjcWeighingWbDetailBinding +import com.lukouguoji.gjc.viewModel.GjcWeighingWbDetailViewModel +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.GjcWeighingRecordBean +import com.lukouguoji.module_base.common.Constant + +/** + * 国际出港计重-运单详情页(5.5寸手机版专属页面,平板端无对应页面) + * + * 由计重记录列表卡片的「查看详情」进入,只读展示运单基本信息, + * 对应设计稿 documents/5.5寸手持端设计文件/03_出港计重/detail.html。 + */ +class GjcWeighingWbDetailActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_gjc_weighing_wb_detail + + override fun viewModelClass() = GjcWeighingWbDetailViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("运单详情") + binding.viewModel = viewModel + viewModel.initOnCreated(intent) + } + + companion object { + @JvmStatic + fun start(context: Context, bean: GjcWeighingRecordBean) { + val starter = Intent(context, GjcWeighingWbDetailActivity::class.java) + .putExtra(Constant.Key.BEAN, bean) + context.startActivity(starter) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcCheckInRecordViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcCheckInRecordViewHolder.kt index 1b2a843..78f0876 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcCheckInRecordViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcCheckInRecordViewHolder.kt @@ -23,5 +23,10 @@ class GjcCheckInRecordViewHolder(view: View) : binding.isEditMode = isEditMode binding.position = position // 传入位置用于显示序号 binding.executePendingBindings() + + // 「修改」按钮(手机独有):打开全屏修改覆层编辑本条记录 + binding.btnEdit?.setOnClickListener { + activity?.openPhoneEdit(record) + } } } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingRecordViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingRecordViewHolder.kt index 93b41e5..bf3ae3c 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingRecordViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingRecordViewHolder.kt @@ -2,12 +2,17 @@ package com.lukouguoji.gjc.holder import android.view.View import com.lukouguoji.gjc.activity.GjcWeighingRecordDetailsActivity +import com.lukouguoji.gjc.activity.GjcWeighingWbDetailActivity import com.lukouguoji.gjc.databinding.ItemGjcWeighingRecordBinding import com.lukouguoji.module_base.base.BaseViewHolder import com.lukouguoji.module_base.bean.GjcWeighingRecordBean /** * 国际出港计重记录列表 ViewHolder + * + * item 布局分平板(layout-sw600dp/item_gjc_weighing_record.xml,含选择图标 iv_icon) + * 与手机(layout/item_gjc_weighing_record.xml,卡片式,地磅图标 iv_scale 进计重明细、 + * 「查看详情」tv_detail 进运单详情)两个变体,单侧独有的 id 需判空调用。 */ class GjcWeighingRecordViewHolder(view: View) : BaseViewHolder(view) { @@ -17,8 +22,8 @@ class GjcWeighingRecordViewHolder(view: View) : binding.bean = bean binding.executePendingBindings() - // 图标点击 - 切换选择状态 - binding.ivIcon.setOnClickListener { + // 图标点击 - 切换选择状态(平板独有) + binding.ivIcon?.setOnClickListener { // 反转checked状态 bean.checked.set(!bean.checked.get()) @@ -26,6 +31,16 @@ class GjcWeighingRecordViewHolder(view: View) : binding.executePendingBindings() } + // 地磅图标点击进计重明细(手机独有) + binding.ivScale?.setOnClickListener { + GjcWeighingRecordDetailsActivity.start(it.context, bean) + } + + // 「查看详情」进运单详情(手机独有页面) + binding.tvDetail?.setOnClickListener { + GjcWeighingWbDetailActivity.start(it.context, bean) + } + // 整行点击跳转到计重明细页 binding.ll.setOnClickListener { GjcWeighingRecordDetailsActivity.start(it.context, bean) diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingViewHolder.kt index 54e8513..9de45ad 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/GjcWeighingViewHolder.kt @@ -1,15 +1,20 @@ package com.lukouguoji.gjc.holder import android.view.View +import com.lukouguoji.gjc.activity.GjcWeighingListActivity import com.lukouguoji.gjc.activity.GjcWeighingStartActivity import com.lukouguoji.gjc.databinding.ItemGjcWeighingBinding import com.lukouguoji.module_base.base.BaseViewHolder -import com.lukouguoji.module_base.common.ConstantEvent -import com.lukouguoji.module_base.impl.FlowBus +import com.lukouguoji.module_base.common.ConstantEvent +import com.lukouguoji.module_base.impl.FlowBus import com.lukouguoji.module_base.bean.GjcWeighingBean /** * 国际出港计重列表 ViewHolder + * + * item 布局分平板(layout-sw600dp/item_gjc_weighing.xml,含选择图标 iv_icon) + * 与手机(layout/item_gjc_weighing.xml,卡片式,含单票提前运抵按钮 btn_pre_arrive)两个变体, + * 单侧独有的 id 在 Binding 基类中为可空字段,需判空调用。 */ class GjcWeighingViewHolder(view: View) : BaseViewHolder(view) { @@ -20,8 +25,8 @@ class GjcWeighingViewHolder(view: View) : binding.position = position binding.executePendingBindings() - // 选择图标点击事件 - 切换选择状态 - binding.ivIcon.setOnClickListener { + // 选择图标点击事件 - 切换选择状态(平板独有) + binding.ivIcon?.setOnClickListener { // 反转checked状态 bean.checked.set(!bean.checked.get()) FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).tryEmit("check_changed") @@ -30,6 +35,11 @@ class GjcWeighingViewHolder(view: View) : binding.executePendingBindings() } + // 卡片内「提前运抵」按钮(手机独有,单票操作) + binding.btnPreArrive?.setOnClickListener { + (it.context as? GjcWeighingListActivity)?.preArriveClick(bean) + } + // 整行点击跳转到开始计重页面 binding.ll.setOnClickListener { GjcWeighingStartActivity.startForAdd(it.context, bean.maWbId) diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordDetailsViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordDetailsViewModel.kt index 7204d4e..7548180 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordDetailsViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordDetailsViewModel.kt @@ -53,6 +53,7 @@ class GjcWeighingRecordDetailsViewModel : BaseViewModel() { val totalPc = MutableLiveData("0") // 总件数 val totalWeight = MutableLiveData("0.0") // 总重量 val weightError = MutableLiveData("0.0%") // 重量误差百分比 + val totalCarWeight = MutableLiveData("0") // 托盘总重(5.5寸手机版顶部卡片,平板布局不引用) // 传递参数(用于API调用) private var prefix = "" @@ -143,6 +144,10 @@ class GjcWeighingRecordDetailsViewModel : BaseViewModel() { val sumWeight = records.sumOf { it.weight } totalWeight.value = String.format("%.2f", sumWeight) + // 计算托盘总重(手机版顶部卡片) + val sumCarWeight = records.sumOf { it.carWeight.toDoubleOrNull() ?: 0.0 } + totalCarWeight.value = String.format("%.2f", sumCarWeight) + // 计算重量误差百分比 val preWeightValue = preWeight.value?.toDoubleOrNull() ?: 0.0 val error = if (sumWeight > 0 && preWeightValue > 0) { @@ -191,6 +196,39 @@ class GjcWeighingRecordDetailsViewModel : BaseViewModel() { saveRecords(records) } + /** + * 5.5寸手机版「修改记录」覆层保存:与 [onSaveClick] 相同的批量更新接口, + * 但保存成功后留在本页(收起覆层 + 重新加载),不关闭页面。仅手机布局调用。 + */ + fun onPhoneSaveClick() { + val records = recordList.value ?: return + + if (!validateRecords(records)) return + + launchLoadingCollect({ + NetApply.api.updateGjcCheckInRecordList(records) + }) { + onSuccess = { result -> + if (result.data == true) { + showToast("保存成功") + // 收起编辑覆层 + isEditMode.value = false + // 通知列表页刷新 + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + // 重新加载本页数据 + loadData() + } else { + showToast("保存失败") + } + } + onFailed = { code, msg -> + showToast("保存失败:$msg") + } + } + } + /////////////////////////////////////////////////////////////////////////// // 业务逻辑 /////////////////////////////////////////////////////////////////////////// diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordViewModel.kt index 43897e9..65a195e 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingRecordViewModel.kt @@ -46,6 +46,32 @@ class GjcWeighingRecordViewModel : BasePageViewModel() { val totalWeight = MutableLiveData("0") // 总重量 val cargoWeight = MutableLiveData("0") // 总货重 + // ========== 5.5寸手机版专属字段(平板不调用 initPhoneExtras,行为零变化) ========== + + /** 目的站(后端支持入参 dest) */ + val destFilter = MutableLiveData("") + + /** 计重人(后端支持入参 opId,下拉复用仓库用户列表) */ + val opUserFilter = MutableLiveData("") + val whsUserList = MutableLiveData>(emptyList()) + + /** 入库日期起/止(后端暂无对应入参,传 opDateStart/opDateEnd 预留参数,见接口问题清单) */ + val checkInDateStart = MutableLiveData("") + val checkInDateEnd = MutableLiveData("") + + /** 由手机形态的 Activity 置 true,平板保持 false(不产生任何额外请求与参数) */ + private var phoneExtrasEnabled = false + + /** + * 开启手机版专属数据:放开「今天」默认日期(设计稿筛选无航班日期)、加载计重人下拉。 + * 仅由手机形态的 Activity 调用。 + */ + fun initPhoneExtras() { + phoneExtrasEnabled = true + flightDate.value = "" + DictUtils.getWHSUserList { whsUserList.postValue(it) } + } + /////////////////////////////////////////////////////////////////////////// // 方法区 /////////////////////////////////////////////////////////////////////////// @@ -130,25 +156,38 @@ class GjcWeighingRecordViewModel : BasePageViewModel() { * 获取列表数据 */ override fun getData() { + // 公共查询条件(列表与统计共用) + val baseParams = mutableMapOf( + "fdate" to flightDate.value!!.ifEmpty { null }, + "fno" to flightNo.value!!.ifEmpty { null }, + "agentCode" to agentCode.value!!.ifEmpty { null }, + "spCode" to spCode.value!!.ifEmpty { null }, + "wbNo" to waybillNo.value!!.ifEmpty { null }, + ) + + // 手机版专属条件(平板 phoneExtrasEnabled 恒为 false,请求体与改造前完全一致) + if (phoneExtrasEnabled) { + // 搜索分流(实测):11 位数字走 wbNo 精确;其余走 likeNo(后端按 8 位 no 匹配) + val key = waybillNo.value?.trim() ?: "" + if (key.isNotEmpty() && key.length != 11) { + baseParams["wbNo"] = null + baseParams["likeNo"] = key + } + baseParams["dest"] = destFilter.value?.ifEmpty { null } + baseParams["opId"] = opUserFilter.value?.ifEmpty { null } + // 入库日期起/止为后端预留参数(暂无对应入参,静默忽略,见接口问题清单) + baseParams["opDateStart"] = checkInDateStart.value?.ifEmpty { null } + baseParams["opDateEnd"] = checkInDateEnd.value?.ifEmpty { null } + } + // 构建查询参数(列表接口) - val listParams = mapOf( + val listParams = (baseParams + mapOf( "pageNum" to pageModel.page, "pageSize" to pageModel.limit, - "fdate" to flightDate.value!!.ifEmpty { null }, - "fno" to flightNo.value!!.ifEmpty { null }, - "agentCode" to agentCode.value!!.ifEmpty { null }, - "spCode" to spCode.value!!.ifEmpty { null }, - "wbNo" to waybillNo.value!!.ifEmpty { null }, - ).toRequestBody() + )).toRequestBody() // 构建查询参数(统计接口 - 使用相同的搜索条件) - val totalParams = mapOf( - "fdate" to flightDate.value!!.ifEmpty { null }, - "fno" to flightNo.value!!.ifEmpty { null }, - "agentCode" to agentCode.value!!.ifEmpty { null }, - "spCode" to spCode.value!!.ifEmpty { null }, - "wbNo" to waybillNo.value!!.ifEmpty { null }, - ).toRequestBody() + val totalParams = baseParams.toRequestBody() // 获取列表数据(显示loading) launchLoadingCollect({ diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingStartViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingStartViewModel.kt index fa338d6..fc45172 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingStartViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingStartViewModel.kt @@ -72,9 +72,22 @@ class GjcWeighingStartViewModel : BaseViewModel() { val spCodeList = MutableLiveData>() // 特码列表 val businessTypeList = MutableLiveData>() // 业务类型列表 - // 托盘车自重(查询获取) + // 托盘车自重(平板:托盘车号查询回填只读;手机:手输,见下方 initPhoneExtras) val carWeight = MutableLiveData("0") + // ========== 5.5寸手机版专属(平板不调用 initPhoneExtras,行为零变化) ========== + + /** 托盘数量(设计稿字段,后端暂无对应入参,提交时传 palletNumber 预留参数,见接口问题清单) */ + val palletNumber = MutableLiveData("") + + /** 手机形态标记:为 true 时提交体额外携带 palletNumber / carWeight(后端静默忽略) */ + private var phoneMode = false + + /** 仅由手机形态的 Activity 调用 */ + fun initPhoneExtras() { + phoneMode = true + } + /** * 初始化 */ @@ -392,6 +405,12 @@ class GjcWeighingStartViewModel : BaseViewModel() { passageWayId = this@GjcWeighingStartViewModel.channel.value remark = pageRemark.value + + // 手机版专属:托盘数量/托盘自重(后端暂无对应入参,静默忽略;平板 phoneMode 恒 false,字段为 null 不进请求体) + if (this@GjcWeighingStartViewModel.phoneMode) { + palletNumber = this@GjcWeighingStartViewModel.palletNumber.value?.ifEmpty { null } + carWeight = this@GjcWeighingStartViewModel.carWeight.value?.ifEmpty { null } + } } // 3. 构建请求数据(GjcMaWb转RequestBody,包含通道号) @@ -423,8 +442,10 @@ class GjcWeighingStartViewModel : BaseViewModel() { maWbBean.value = maWbBean.value?.apply { carId = null remark = null + palletNumber = null } carWeight.value = "0" + this@GjcWeighingStartViewModel.palletNumber.value = "" } else { showToast(result.msg.noNull("分托计重失败")) } @@ -502,7 +523,10 @@ class GjcWeighingStartViewModel : BaseViewModel() { "remark" to pageRemark.value, "checkIn" to "1", // 收运状态设置为已收运 "passageWayId" to channel.value, // 通道号参数 - "passageWay" to (channelList.value?.firstOrNull{ it.value == channel.value }?.key ?: "") + "passageWay" to (channelList.value?.firstOrNull{ it.value == channel.value }?.key ?: ""), + // 手机版专属预留参数(平板 phoneMode 恒 false → null → removeEmptyOrNull 移除,请求体不变) + "palletNumber" to (if (phoneMode) palletNumber.value?.ifEmpty { null } else null), + "carWeight" to (if (phoneMode) carWeight.value?.ifEmpty { null } else null) ).toRequestBody(removeEmptyOrNull = true) launchLoadingCollect({ diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingViewModel.kt index 0559c43..feabb0f 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingViewModel.kt @@ -55,15 +55,80 @@ class GjcWeighingViewModel : BasePageViewModel() { // 全选状态 val isAllChecked = MutableLiveData(false) - - fun onItemCheckChanged() { - updateCheckAllStatus() - } - - fun updateCheckAllStatus() { - val list = pageModel.rv?.commonAdapter()?.items as? List ?: return - isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() } - } + + // ========== 5.5寸手机版专属字段(平板不调用 initPhoneExtras,行为零变化) ========== + + /** 手机版顶部搜索关键字(运单号/航班号混输,getData 内分流:含字母→fno,纯数字→likeNo 模糊) */ + val searchKey = MutableLiveData("") + + /** 主页三格统计:待计重(checkIn=0)/ 计重中(checkIn=2)数量 */ + val pendingCount = MutableLiveData("0") + val weighingCount = MutableLiveData("0") + + /** 手机版筛选弹层字段。通道号/承运人/运单类型后端暂无查询入参(见接口问题清单),传预留参数名 */ + val channelFilter = MutableLiveData("") // 通道号 → passageWayId + val carrierFilter = MutableLiveData("") // 承运人 → by0 + val awbTypeFilter = MutableLiveData("") // 运单类型 → awbType + val channelList = MutableLiveData>(emptyList()) + val awbTypeList = MutableLiveData>(emptyList()) + + /** 由手机形态的 Activity 置 true,平板保持 false(不产生任何额外请求与参数) */ + private var phoneExtrasEnabled = false + + /** + * 开启手机版专属数据:放开「今天」默认日期(设计稿主页无日期筛选)、加载筛选弹层字典。 + * 仅由手机形态的 Activity 调用。 + */ + fun initPhoneExtras() { + phoneExtrasEnabled = true + flightDate.value = "" + DictUtils.getGjcChannelList { list -> + channelList.postValue(listOf(KeyValue("全部", "")) + list) + } + DictUtils.getWaybillTypeList2(ieFlag = "E", type = "IO") { + awbTypeList.postValue(it) + } + } + + /** + * 单票提前运抵(手机版卡片内按钮;平板走底部批量 [arrivedAhead]) + */ + fun arrivedAheadSingle(bean: GjcWeighingBean) { + if (bean.arriveFlag == "1") { + showToast("该运单已提前运抵") + return + } + val maWbList = listOf( + GjcMaWb( + maWbId = bean.maWbId, + no = bean.no, + prefix = bean.prefix, + wbNo = bean.wbNo, + arriveFlag = "1" + ) + ) + launchLoadingCollect({ NetApply.api.preArrive(maWbList) }) { + onSuccess = { + showToast("提前运抵成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + refresh() + } + onFailed = { code, msg -> + showToast(msg.noNull("提前运抵失败")) + } + } + } + + fun onItemCheckChanged() { + updateCheckAllStatus() + } + + fun updateCheckAllStatus() { + val list = pageModel.rv?.commonAdapter()?.items as? List ?: return + isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() } + } /////////////////////////////////////////////////////////////////////////// // 方法区 @@ -185,25 +250,41 @@ class GjcWeighingViewModel : BasePageViewModel() { * 获取列表数据 */ override fun getData() { + // 公共查询条件(列表与统计共用) + val baseParams = mutableMapOf( + "fdate" to flightDate.value!!.ifEmpty { null }, + "fno" to flightNo.value!!.ifEmpty { null }, + "agentCode" to agentCode.value!!.ifEmpty { null }, + "spCode" to spCode.value!!.ifEmpty { null }, + "wbNo" to waybillNo.value!!.ifEmpty { null }, + ) + + // 手机版专属条件(平板 phoneExtrasEnabled 恒为 false,请求体与改造前完全一致) + if (phoneExtrasEnabled) { + val key = searchKey.value?.trim() ?: "" + if (key.isNotEmpty()) { + // 分流规则(实测):含字母 → 航班号;11 位数字 → wbNo 精确; + // 其余数字 → likeNo(后端按 8 位 no 匹配,并非任意模糊) + when { + key.any { it.isLetter() } -> baseParams["fno"] = key + key.length == 11 -> baseParams["wbNo"] = key + else -> baseParams["likeNo"] = key + } + } + // 以下三个为后端预留参数(暂无对应入参,后端静默忽略,见接口问题清单) + baseParams["passageWayId"] = channelFilter.value?.ifEmpty { null } + baseParams["by0"] = carrierFilter.value?.ifEmpty { null } + baseParams["awbType"] = awbTypeFilter.value?.ifEmpty { null } + } + // 构建查询参数(列表接口) - val listParams = mapOf( + val listParams = (baseParams + mapOf( "pageNum" to pageModel.page, "pageSize" to pageModel.limit, - "fdate" to flightDate.value!!.ifEmpty { null }, - "fno" to flightNo.value!!.ifEmpty { null }, - "agentCode" to agentCode.value!!.ifEmpty { null }, - "spCode" to spCode.value!!.ifEmpty { null }, - "wbNo" to waybillNo.value!!.ifEmpty { null }, - ).toRequestBody() + )).toRequestBody() // 构建查询参数(统计接口 - 使用相同的搜索条件) - val totalParams = mapOf( - "fdate" to flightDate.value!!.ifEmpty { null }, - "fno" to flightNo.value!!.ifEmpty { null }, - "agentCode" to agentCode.value!!.ifEmpty { null }, - "spCode" to spCode.value!!.ifEmpty { null }, - "wbNo" to waybillNo.value!!.ifEmpty { null }, - ).toRequestBody() + val totalParams = baseParams.toRequestBody() // 获取列表数据(显示loading) launchLoadingCollect({ @@ -225,6 +306,21 @@ class GjcWeighingViewModel : BasePageViewModel() { totalWeight.value = (data?.totalWeight ?: 0.0).toString() } } + + // 手机版三格统计:待计重 / 计重中(各带一次 checkIn 条件的统计请求,仅手机调用) + if (phoneExtrasEnabled) { + listOf("0" to pendingCount, "2" to weighingCount).forEach { (state, liveData) -> + launchCollect({ + NetApply.api.getGjcWeighingStatistics( + (baseParams + mapOf("checkIn" to state)).toRequestBody() + ) + }) { + onSuccess = { result -> + liveData.value = (result.data?.wbNumber ?: 0).toString() + } + } + } + } } /** @@ -234,7 +330,10 @@ class GjcWeighingViewModel : BasePageViewModel() { if (resultCode == Activity.RESULT_OK && data != null) { when (requestCode) { Constant.RequestCode.WAYBILL -> { - waybillNo.value = data.getStringExtra(Constant.Result.CODED_CONTENT) + val content = data.getStringExtra(Constant.Result.CODED_CONTENT) + // 手机版扫码写入顶部搜索框,平板写入原运单号搜索条 + if (phoneExtrasEnabled) searchKey.value = content + else waybillNo.value = content refresh() } } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingWbDetailViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingWbDetailViewModel.kt new file mode 100644 index 0000000..0de37cf --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcWeighingWbDetailViewModel.kt @@ -0,0 +1,30 @@ +package com.lukouguoji.gjc.viewModel + +import android.content.Intent +import androidx.lifecycle.MutableLiveData +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.GjcWeighingRecordBean +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.ktx.showToast + +/** + * 国际出港计重-运单详情 ViewModel(5.5寸手机版专属页面) + * + * 只读展示计重记录列表传入的运单信息,无接口请求。 + * 注:设计稿中的「通道号」字段在 /IntExpCheckIn/checked/pageQuery 出参中不存在(后端缺口, + * 见接口问题清单),布局侧空值兜底显示 "-"。 + */ +class GjcWeighingWbDetailViewModel : BaseViewModel() { + + // 运单信息(从计重记录列表页传入) + val bean = MutableLiveData(GjcWeighingRecordBean()) + + fun initOnCreated(intent: Intent) { + val data = intent.getSerializableExtra(Constant.Key.BEAN) as? GjcWeighingRecordBean + if (data != null) { + bean.value = data + } else { + showToast("参数错误") + } + } +} diff --git a/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_list.xml b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_list.xml new file mode 100644 index 0000000..353f09f --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_list.xml @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_record_details.xml b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_record_details.xml new file mode 100644 index 0000000..f3fca7f --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_record_details.xml @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_record_list.xml b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_record_list.xml new file mode 100644 index 0000000..0f8db9d --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_record_list.xml @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_start.xml b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_start.xml new file mode 100644 index 0000000..3e036fe --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/activity_gjc_weighing_start.xml @@ -0,0 +1,496 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/item_gjc_check_in_record.xml b/module_gjc/src/main/res/layout-sw600dp/item_gjc_check_in_record.xml new file mode 100644 index 0000000..e1fcc60 --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/item_gjc_check_in_record.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/item_gjc_weighing.xml b/module_gjc/src/main/res/layout-sw600dp/item_gjc_weighing.xml new file mode 100644 index 0000000..3723c6a --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/item_gjc_weighing.xml @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout-sw600dp/item_gjc_weighing_record.xml b/module_gjc/src/main/res/layout-sw600dp/item_gjc_weighing_record.xml new file mode 100644 index 0000000..e1e8d7c --- /dev/null +++ b/module_gjc/src/main/res/layout-sw600dp/item_gjc_weighing_record.xml @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_gjc_weighing_list.xml b/module_gjc/src/main/res/layout/activity_gjc_weighing_list.xml index 165cefc..f397371 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_weighing_list.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_weighing_list.xml @@ -1,222 +1,301 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_gjc_weighing_record_details.xml b/module_gjc/src/main/res/layout/activity_gjc_weighing_record_details.xml index 0c5d9f8..b6405b0 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_weighing_record_details.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_weighing_record_details.xml @@ -1,270 +1,257 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_gjc_weighing_record_list.xml b/module_gjc/src/main/res/layout/activity_gjc_weighing_record_list.xml index 381001f..20c4e3c 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_weighing_record_list.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_weighing_record_list.xml @@ -1,183 +1,301 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml b/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml index 3e036fe..c798f17 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml @@ -1,496 +1,286 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/activity_gjc_weighing_wb_detail.xml b/module_gjc/src/main/res/layout/activity_gjc_weighing_wb_detail.xml new file mode 100644 index 0000000..54f9593 --- /dev/null +++ b/module_gjc/src/main/res/layout/activity_gjc_weighing_wb_detail.xml @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_gjc_check_in_record.xml b/module_gjc/src/main/res/layout/item_gjc_check_in_record.xml index e1fcc60..79ff69a 100644 --- a/module_gjc/src/main/res/layout/item_gjc_check_in_record.xml +++ b/module_gjc/src/main/res/layout/item_gjc_check_in_record.xml @@ -1,95 +1,196 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_gjc_weighing.xml b/module_gjc/src/main/res/layout/item_gjc_weighing.xml index 3723c6a..12b55aa 100644 --- a/module_gjc/src/main/res/layout/item_gjc_weighing.xml +++ b/module_gjc/src/main/res/layout/item_gjc_weighing.xml @@ -1,316 +1,141 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_gjc_weighing_record.xml b/module_gjc/src/main/res/layout/item_gjc_weighing_record.xml index e1e8d7c..8f23284 100644 --- a/module_gjc/src/main/res/layout/item_gjc_weighing_record.xml +++ b/module_gjc/src/main/res/layout/item_gjc_weighing_record.xml @@ -1,272 +1,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_p/src/main/java/com/sixin/module_p/ui/enter/gj/GjViewModel.kt b/module_p/src/main/java/com/sixin/module_p/ui/enter/gj/GjViewModel.kt index 6bcb6af..15e7b15 100644 --- a/module_p/src/main/java/com/sixin/module_p/ui/enter/gj/GjViewModel.kt +++ b/module_p/src/main/java/com/sixin/module_p/ui/enter/gj/GjViewModel.kt @@ -48,6 +48,12 @@ class GjViewModel : BaseViewModel() { Constant.AuthName.GjcIntExpOutHandover, ARouterConstants.ACTIVITY_URL_INT_EXP_OUT_HANDOVER ), + ActionBean( + "出港计重", + R.drawable.img_gjc_chugangjizhong, + Constant.AuthName.GjcCheckWeighing, + ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_LIST + ), // ULD管理属综合管理业务(Pad 端在「综合管理」菜单组),手机端首页暂无综合 Tab,挂在国际 Tab 下 ActionBean( "ULD管理", diff --git a/module_p/src/main/res/drawable-xxhdpi/img_gjc_chugangjizhong.png b/module_p/src/main/res/drawable-xxhdpi/img_gjc_chugangjizhong.png new file mode 100644 index 0000000..57ab8e4 Binary files /dev/null and b/module_p/src/main/res/drawable-xxhdpi/img_gjc_chugangjizhong.png differ